home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2002 #11 / Amiga Plus CD - 2002 - No. 11.iso / Tools / Development / reportplus / source / f6.c < prev    next >
C/C++ Source or Header  |  2002-10-27  |  142KB  |  3,991 lines

  1. #include <exec/types.h>
  2. #include <exec/memory.h>
  3. #include <intuition/intuition.h>
  4. #include <intuition/gadgetclass.h>
  5. #include <libraries/iffparse.h>
  6. #include <dos/dos.h>
  7. #include <dos/datetime.h>
  8.  
  9. #include <clib/alib_protos.h>
  10. #include <clib/exec_protos.h>
  11. #include <clib/intuition_protos.h>
  12. #include <clib/iffparse_protos.h>
  13. #include <clib/dos_protos.h>
  14.  
  15. #define ALL_REACTION_CLASSES
  16. #define ALL_REACTION_MACROS
  17. #include <reaction/reaction.h>
  18.  
  19. #include <ctype.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include "rp.h"
  23.  
  24. #define BYTESPERLINE 12 // how many bytes to print per line
  25. #define LABELLENGTH  25
  26.  
  27. #define ITEMS 255
  28. MODULE struct
  29. {   TEXT   name[5];
  30.     ULONG  bytes;
  31.     UBYTE* DataPtr;
  32. } contents[ITEMS + 1];
  33.  
  34. #define FORMS         91
  35.  
  36. #define CD             1
  37. #define OBSOLETE       2
  38. #define PRIVATE        4
  39. #define PROPOSAL       8
  40. #define RESERVED      16
  41. #define RKM           32
  42. #define STANDARD      64
  43. #define UNREGISTERED 128
  44.  
  45. #define IFFXCHARS     13
  46.  
  47. MODULE void iffquery(void);
  48. MODULE void PrintTopChunk(void);
  49. MODULE void readiff(void);
  50. MODULE void tellchunk(UWORD which);
  51. MODULE void chunkdesc(STRPTR desc, ABOOL isknown);
  52. MODULE void binarize(UBYTE data);
  53. MODULE void hexalize(UBYTE data);
  54. MODULE ULONG getulong(UBYTE* start);
  55. MODULE SLONG getslong(UBYTE* start);
  56. MODULE ULONG getuword(UBYTE* start);
  57. MODULE SLONG getsword(UBYTE* start);
  58. MODULE SLONG getsbyte(UBYTE* start);
  59. MODULE void writeiffgadgets(void);
  60. MODULE void dotextattr(UBYTE* offset);
  61. MODULE void docountry(UBYTE* offset);
  62. MODULE void label(STRPTR text);
  63. MODULE void dobool(UBYTE thebool);
  64. MODULE void snumcat(SLONG thenumber, ABOOL finished);
  65. MODULE void unumcat(ULONG thenumber, ABOOL finished);
  66. MODULE void interpret(ULONG tablenum, ULONG value);
  67.  
  68. #define TABLENUMS    54
  69. #define TABLEENTRIES 13
  70.  
  71. struct
  72. {   UBYTE  entries;
  73.     STRPTR tablestring[TABLEENTRIES + 1];
  74. } table[TABLENUMS + 1] =
  75. { { 2, // 0
  76.     "XON",  // HSHAKE_XON
  77.     "RTS",  // HSHAKE_RTS
  78.     "None"  // HSHAKE_NONE
  79.   },
  80.   { 2, // 1
  81.     "none",
  82.     "superscript",
  83.     "subscript"
  84.   },
  85.   { 2, // 2
  86.     "Unknown",
  87.     "No",
  88.     "Yes"
  89.   },
  90.   { 4, // 3
  91.     "None",
  92.     "Even",
  93.     "Odd",
  94.     "Mark",
  95.     "Space"
  96.   },
  97.   { 2, // 4
  98.     "name",
  99.     "date",
  100.     "size"
  101.   },
  102.   { 2, // 5
  103.     "first",
  104.     "mix",
  105.     "last"
  106.   },
  107.   { 1, // 6
  108.     "ascending",
  109.     "descending"
  110.   },
  111.   { 5, // 7
  112.     "default",
  113.     "centre in window",
  114.     "centre on screen",
  115.     "top left of window",
  116.     "top left of screen",
  117.     "mouse pointer"
  118.   },
  119.   { 2, // 8
  120.     "Workbench",
  121.     "system",
  122.     "screen"
  123.   },
  124.   { 3, // 9
  125.     "JAM1",
  126.     "JAM2",
  127.     "complement",
  128.     "inverse video"
  129.   },
  130.   { 1, // 10
  131.     "PostScript",  // DM_POSTSCRIPT
  132.     "pass through" // DM_PASSTHROUGH
  133.   },
  134.   { 3, // 11
  135.     "US Letter",   // PF_USLETTER
  136.     "US Legal",    // PF_USLEGAL
  137.     "A4",          // PF_A4
  138.     "custom"       // PF_CUSTOM
  139.   },
  140.   { 8, // 12
  141.     "Courier",
  142.     "Times",
  143.     "Helvetica",
  144.     "Helvetica Narrow",
  145.     "Avant Garde",
  146.     "Bookman",
  147.     "New Century",
  148.     "Palantino",
  149.     "Zapf Chancery"
  150.   },
  151.   { 2, // 13
  152.     "normal",
  153.     "compressed",
  154.     "expanded"
  155.   },
  156.   { 1, // 14
  157.     "portrait",
  158.     "landscape"
  159.   },
  160.   { 4, // 15
  161.     "4 characters",
  162.     "8 characters",
  163.     "quarter-inch",
  164.     "half-inch",
  165.     "inch"
  166.   },
  167.   { 1, // 16
  168.     "positive",
  169.     "negative"
  170.   },
  171.   { 2, // 17
  172.     "black and white", // SHAD_BW
  173.     "greyscale",       // SHAD_GREYSCALE
  174.     "colour"           // SHAD_COLOR
  175.   },
  176.   { 4, // 18
  177.     "default",    // DITH_DEFAULT
  178.     "dotty",      // DITH_DOTTY
  179.     "vertical",   // DITH_VERT
  180.     "horizontal", // DITH_HORIZ
  181.     "diagonal"    // DITH_DIAG
  182.   },
  183.   { 1, // 19
  184.     "horizontal", // ASP_HORIZ
  185.     "vertical"    // ASP_VERT
  186.   },
  187.   { 6, // 20
  188.     "aspect as is", // ST_ASPECT_ASIS
  189.     "aspect wide",  // ST_ASPECT_WIDE
  190.     "aspect tall",  // ST_ASPECT_TALL
  191.     "aspect both",  // ST_ASPECT_BOTH
  192.     "fits wide",    // ST_FITS_WIDE
  193.     "fits tall",    // ST_FITS_TALL
  194.     "fits both"     // ST_FITS_BOTH
  195.   },
  196.   { 3, // 21
  197.     "none",       // CENT_NONE
  198.     "horizontal", // CENT_HORIZ
  199.     "vertical",   // CENT_VERT
  200.     "both"        // CENT_BOTH
  201.   },
  202.   { 3, // 22
  203.     "black and white", // PS_BW
  204.     "greyscale 1",     // PS_GREYSCALE
  205.     "colour",          // PS_COLOR
  206.     "greyscale 2"      // PS_GREY_SCALE2
  207.   },
  208.   { 4, // 23
  209.     "ignore",         // PD_IGNORE
  210.     "bounded",        // PD_BOUNDED
  211.     "absolute",       // PD_ABSOLUTE
  212.     "printer pixels", // PD_PIXEL
  213.     "multiply"        // PD_MULTIPLY
  214.   },
  215.   { 2, // 24
  216.     "ordered",        // PD_ORDERED
  217.     "halftone",       // PD_HALFTONE
  218.     "Floyd-Steinberg" // PD_FLOYD
  219.   },
  220.   { 1, // 25
  221.     "parallel",       // PP_PARALLEL
  222.     "serial"          // PP_SERIAL
  223.   },
  224.   { 1, // 26
  225.     "fanfold",        // PT_FANFOLD
  226.     "single sheet"    // PT_SINGLE
  227.   },
  228.   { 13, // 27
  229.     "US Letter",      // PS_US_LETTER
  230.     "US Legal",       // PS_US_LEGAL
  231.     "narrow tractor", // PS_N_TRACTOR
  232.     "wide tractor",   // PS_W_TRACTOR
  233.     "custom",         // PS_CUSTOM
  234.     "A0: 841x1189mm", // PS_EURO_A0
  235.     "A1: 594x841mm",  // PS_EURO_A1
  236.     "A2: 420x594mm",  // PS_EURO_A2
  237.     "A3: 297x420mm",  // PS_EURO_A3
  238.     "A4: 210x297mm",  // PS_EURO_A4
  239.     "A5: 148x210mm",  // PS_EURO_A5
  240.     "A6: 105x148mm",  // PS_EURO_A6
  241.     "A7: 74x105mm",   // PS_EURO_A7
  242.     "A8: 52x74mm",    // PS_EURO_A8
  243.   },
  244.   { 2, // 28
  245.     "Pica",  // PP_PICA
  246.     "Elite", // PP_ELITE
  247.     "Fine"   // PP_FINE
  248.   },
  249.   { 1, // 29
  250.     "6 lines per inch", // PS_SIX_LPI
  251.     "8 lines per inch", // PS_EIGHT_LPI
  252.   },
  253.   { 1, // 30
  254.     "draft", // PQ_DRAFT
  255.     "letter" // PQ_LETTER
  256.   },
  257.   { 1, // 31
  258.     "beep",  // SPTYPE_BEEP
  259.     "sample" // SPTYPE_SAMPLE
  260.   },
  261.   { 2, // 32
  262.     "Workbench", // WBP_ROOT
  263.     "window",    // WBP_DRAWER
  264.     "screen"     // WBP_SCREEN
  265.   },
  266.   { 1, // 33
  267.     "normal",
  268.     "busy"
  269.   },
  270.   { 6, // 34
  271.     "default",        // POINTERXRESN_DEFAULT
  272.     "140ns",          // POINTERXRESN_140NS
  273.     "70ns",           // POINTERXRESN_70NS
  274.     "35ns",           // POINTERXRESN_35NS
  275.     "screen",         // POINTERXRESN_SCREENRES
  276.     "low resolution", // POINTERXRESN_LORES
  277.     "high resolution" // POINTERXRESN_HIRES
  278.   },
  279.   { 4, // 35
  280.     "default",           // POINTERYRESN_DEFAULT
  281.     "high non-aspect",   // POINTERYRESN_HIGH
  282.     "high aspect",       // POINTERYRESN_HIGHASPECT
  283.     "screen non-aspect", // POINTERYRESN_SCREENRES
  284.     "screen aspect"      // POINTERYRESN_SCREENRESASPECT
  285.   },
  286.   { 3, // 36
  287.     "none",
  288.     "low",
  289.     "high",
  290.     "all"
  291.   },
  292.   { 4, // 37
  293.     "GadTools 2:1",
  294.     "ReAction 1:1",
  295.     "ReAction 2:1",
  296.     "XEN 2:1",
  297.     "XEN 1:1"
  298.   },
  299.   { 2, // 38
  300.     "GadTools", // GLT_GT
  301.     "flat",     // GLT_FLAT
  302.     "3D"        // GLT_3D
  303.   },
  304.   { 2, // 39
  305.     "centre",
  306.     "left",
  307.     "right"
  308.   },
  309.   { 1, // 40
  310.     "Find by name",
  311.     "Find on MIDI"
  312.   },
  313.   { 4, // 41
  314.     "1, 2, 3...",
  315.     "I, II, III...",
  316.     "i, ii, iii...",
  317.     "A, B, C...",
  318.     "a, b, c..."
  319.   },
  320.   { 3, // 42
  321.     "none",
  322.     "left",
  323.     "right",
  324.     "both"
  325.   },
  326.   { 3, // 43
  327.     "left",
  328.     "centre",
  329.     "right",
  330.     "full"
  331.   },
  332.   { 3, // 44
  333.     "left",
  334.     "centre",
  335.     "right",
  336.     "decimal"
  337.   },
  338.   { 3, // 45
  339.     "opaque",
  340.     "mask plane",
  341.     "transparent colour",
  342.     "lasso"
  343.   },
  344.   { 1, // 46
  345.     "none",
  346.     "byte run encoding"
  347.   },
  348.   { 2, // 47
  349.     "no looping",
  350.     "forwards looping",
  351.     "forwards/backwards looping"
  352.   },
  353.   { 1, // 48
  354.     "none",
  355.     "Fibonacci-delta encoding"
  356.   },
  357.   { 6, // 49
  358.     "set directly",
  359.     "XOR ILBM",
  360.     "long delta",
  361.     "short delta",
  362.     "short/long delta",
  363.     "byte vertical delta",
  364.     "stereo op 5"
  365.   },
  366.   { 3, // 50
  367.     "metric",   // MS_ISO
  368.     "American", // MS_AMERICAN
  369.     "Imperial", // MS_IMPERIAL
  370.     "British"   // MS_BRITISH
  371.   },
  372.   { 1, // 51
  373.     "No", // SS_NOSPACE
  374.     "Yes" // SS_SPACE
  375.   },
  376.   { 4, // 52
  377.     "parentheses around amount and symbol", // SP_PARENS
  378.     "sign is before amount and symbol",     // SP_PREC_ALL
  379.     "sign is after amount and symbol",      // SP_SUCC_ALL
  380.     "sign is before symbol",                // SP_PREC_CURR
  381.     "sign is after symbol"                  // SP_SUCC_CURR
  382.   },
  383.   { 1, // 53
  384.     "symbol is before amount", // CSP_PRECEDES
  385.     "symbol is after amount"   // CSP_SUCCEEDS
  386.   },
  387.   { 6, // 54
  388.     "Sunday",
  389.     "Monday",
  390.     "Tuesday",
  391.     "Wednesday",
  392.     "Thursday",
  393.     "Friday",
  394.     "Saturday"
  395. } };
  396.  
  397. /* Text error messages for possible IFFERR_#? returns from various IFF
  398.  * routines. To get the index into this array, take your IFFERR code,
  399.  * negate it, and subtract one.
  400.  * idx = -error - 1;
  401.  */
  402. STRPTR errormsgs[] =
  403. {   "End of file (not an error).",
  404.     "End of context (not an error).",
  405.     "No lexical scope.",
  406.     "Insufficient memory.",
  407.     "Stream read error.",
  408.     "Stream write error.",
  409.     "Stream seek error.",
  410.     "File is corrupt.",
  411.     "IFF syntax error.",
  412.     "Not an IFF file.",
  413.     "Required call-back hook missing.",
  414.     "Return to client. You should never see this."
  415. };
  416.  
  417. // from rp.c
  418. IMPORT SBYTE              page;
  419. IMPORT struct Window*     MainWindowPtr;
  420. IMPORT struct TextAttr    Topaz8;
  421. IMPORT TEXT               aslresult[VLONGFIELD + 1],
  422.                           weekdaystring[LEN_DATSTRING],
  423.                           datestring[LEN_DATSTRING],
  424.                           timestring[LEN_DATSTRING],
  425.                           IOBuffer[LONGESTFIELD + 1];
  426. IMPORT Object*            WinObject[FUNCTIONS + 1]; // note that WindowObject is a reserved macro
  427. IMPORT struct Menu*       MenuPtr;
  428. IMPORT struct Screen*     ScreenPtr;
  429.  
  430. MODULE ABOOL             known, first;
  431. MODULE struct IFFHandle* IFFHandle             = NULL;
  432. MODULE struct List       List1,
  433.                          List2;
  434. MODULE TEXT  queryform[5] = "",
  435.              tempstring1[VLONGFIELD + 1],
  436.              tempstring2[13], // only for use with numbers
  437.              tempstring3[VLONGFIELD + 1];
  438. MODULE ULONG items        = 0; // value of this is actual number of items allocated
  439. MODULE UWORD selectedform  = 0,
  440.              selectedchunk = 0;
  441. MODULE struct Gadget*    iff_gadgets[GIDS_6 + 1];
  442.     
  443. AGLOBAL struct IFFStruct iff;
  444.  
  445. MODULE struct
  446. {   UBYTE  flags;
  447.     TEXT   name[5];
  448.     STRPTR desc;
  449.     STRPTR contributor;
  450. } form[FORMS + 1] =
  451. {   STANDARD | RKM | CD,      "8SVX", "EA IFF 85 8-bit sound sample form",                    "EA/CBM",
  452.     RKM | CD,                 "AIFF", "Audio 1-32 bit samples",                               "Apple",
  453.     RKM | CD,                 "ACBM", "Amiga Contiguous Bitmap",                              "CBM",
  454.     UNREGISTERED,             "AHAM", "?",                                                    "?",
  455.     RKM | CD,                 "ANBM", "ANimated BitMap form",                                 "EA",
  456.     RKM | CD,                 "ANIM", "Cel ANIMation form",                                   "Sparta/Aegis",
  457.     PROPOSAL,                 "ARC ", "ARChive format",                                       "?",
  458.     UNREGISTERED,             "ARES", "?",                                                    "?",
  459.     RESERVED,                 "ATXT", "Temporarily reserved",                                 "?",
  460.     PRIVATE,                  "AVCF", "AmigaVision Flow",                                     "CBM",
  461.     NULL,                     "BANK", "Soundquest Editor/Librarian MIDI Sysex dump",          "?",
  462.     NULL,                     "BBSD", "BBS Database",                                         "Phalanx Software",
  463.     PRIVATE,                  "C100", "?",                                                    "Cloanto",
  464.     STANDARD,                 "CAT ", "EA IFF 85 group identifier",                           "EA/CBM",
  465.     PROPOSAL,                 "CELP", "Compressed ZyXEL voice data",                          "?",
  466.     RESERVED,                 "CHBM", "Chunky bitmap",                                        "Eric Lavitsky",
  467.     NULL,                     "CLIP", "CAT CLIP to hold various formats in clipboard",        "CBM",
  468.     PROPOSAL | CD,            "CMUS", "Common MUsical Score",                                 "Talin (David Joiner)",
  469.     NULL,                     "CPFM", "Cloanto Personal FontMaker",                           "Cloanto",
  470.     UNREGISTERED,             "CTLG", "Language CaTaLoG",                                     "CBM",
  471.     NULL,                     "DCCL", "DCTV paint clip",                                      "?",
  472.     NULL,                     "DCPA", "DCTV paint palette",                                   "?",
  473.     NULL,                     "DCTV", "DCTV raw picture file",                                "?",
  474.     PRIVATE,                  "DECK", "Inovatronics CanDo",                                   "Innovatronics",
  475.     CD,                       "DEEP", "Chunky pixel image files (used in TV Paint)",          "Amiga Centre Scotland",
  476.     RKM | CD,                 "DR2D", "2D object standard format",                            "Ross Cunniff & John Orr",
  477.     RESERVED,                 "DRAW", "?",                                                    "Jim Bayless",
  478.     CD,                       "DTYP", "DataTYPes identification",                             "Amiga, Inc.",
  479.     PROPOSAL | CD,            "EXEC", "Executable (loadseg-able) code",                       "Chris Ludwig",
  480.     RKM | CD,                 "FANT", "Fantavision movie format",                             "Broderbund",
  481.     OBSOLETE | PRIVATE,       "FAX3", "Facsimile image",                                      "GPSoftware",
  482.     CD,                       "FAXX", "Facsimile image",                                      "Atlantis Design Group",
  483.     RESERVED,                 "FIGR", "Deluxe Video",                                         "EA",
  484.     NULL,                     "FILM", "LIST FILM - stores ILBMs with interleaved 8SVX audio", "?",
  485.     RESERVED,                 "FNTR", "Raster font",                                          "EA",
  486.     RESERVED,                 "FNTV", "Vector font",                                          "EA",
  487.     STANDARD,                 "FORM", "Group identifier",                                     "EA/CBM",
  488.     STANDARD | RKM,           "FTXT", "Formatted TeXT",                                       "EA/CBM",
  489.     PROPOSAL | PRIVATE,       "GRYP", "Byteplane storage",                                    "?",
  490.     RESERVED,                 "GSCR", "General music SCoRe",                                  "EA",
  491.     PROPOSAL | PRIVATE,       "GUI ", "User interface storage",                               "?",
  492.     RKM | CD,                 "HEAD", "Flow idea processor",                                  "New Horizons Software",
  493.     STANDARD | RKM | CD,      "ILBM", "EA IFF 85 raster bitmap form",                         "EA/CBM",
  494.     RESERVED,                 "IOBJ", "?",                                                    "Seven Seas Software",
  495.     RESERVED,                 "IODK", "?",                                                    "Merging Technologies",
  496.     RESERVED,                 "ITRF", "?",                                                    "?",
  497.     RESERVED,                 "JMOV", "?",                                                    "Merging Technologies",
  498.     STANDARD,                 "LIST", "EA IFF 85 group identifier",                           "EA/CBM",
  499.     RESERVED,                 "MFAX", "Facsimile?",                                           "TKR GmbH & Co.",
  500.     NULL,                     "MIDI", "MIDI?",                                                "Circum Design",
  501.     PRIVATE,                  "MOVI", "LIST MOVIe?",                                          "?",
  502.     PRIVATE,                  "MSCX", "Music-X format",                                       "?",
  503.     RESERVED,                 "MSMP", "Temporarily reserved",                                 "?",
  504.     RKM | CD,                 "MTRX", "Numerical data storage (MathVision)",                  "Seven Seas Software",
  505.     NULL,                     "NSEQ", "Numerical sequence",                                   "Stockhausen GmbH",
  506.     PROPOSAL | CD,            "OB3D", "Standard 3D object",                                   "?",
  507.     RKM | CD,                 "PGTB", "ProGram TraceBack",                                    "SAS Institute",
  508.     RESERVED,                 "PICS", "Macintosh picture",                                    "EA",
  509.     RESERVED | OBSOLETE,      "PLBM", "?",                                                    "EA",
  510.     RESERVED | PROPOSAL | CD, "PMBC", "24-bit accurate images",                               "Black Belt Systems",
  511.     RESERVED | PRIVATE,       "PREF", "User preferences data",                                "CBM",
  512.     STANDARD,                 "PROP", "Group identifier",                                     "EA/CBM",
  513.     RKM | CD,                 "PRSP", "DPaint IV perspective move form",                      "EA",
  514.     NULL,                     "PTCH", "Patch file",                                           "SAS Institute",
  515.     RESERVED,                 "PTXT", "Temporarily reserved",                                 "?",
  516.     PRIVATE,                  "RGB4", "4-bit RGB",                                            "?",
  517.     RKM | CD,                 "RGB8", "RGB image (Turbo Silver)",                             "Impulse",
  518.     RKM | CD,                 "RGBN", "RGB image (Turbo Silver)",                             "Impulse",
  519.     RESERVED,                 "RGBX", "Temporarily reserved",                                 "?",
  520.     PRIVATE,                  "ROXN", "Animation",                                            "?",
  521.     UNREGISTERED,             "RSND", "Sampled SouND",                                        "Achim Stegemann",
  522.     RKM | CD,                 "SAMP", "SAMPled sound",                                        "Jim Fiore & Jeff Glatt",
  523.     PRIVATE,                  "SC3D", "SCene format (Sculpt-3D)",                             "?",
  524.     PRIVATE,                  "SHAK", "SHAKespeare format",                                   "?",
  525.     RESERVED | PRIVATE,       "SHO1", "?",                                                    "Gary Bonham",
  526.     RESERVED | PRIVATE,       "SHOW", "?",                                                    "Gary Bonham",
  527.     STANDARD | RKM,           "SMUS", "Simple MUsic Score",                                   "EA/CBM",
  528.     CD,                       "SPLT", "File SPLiTting system",                                "ASDG",
  529.     RESERVED,                 "SSRE", "?",                                                    "Merging Technologies",
  530.     UNREGISTERED,             "SWRT", "?",                                                    "?",
  531.     NULL,                     "SYTH", "SoundQuest Master Librarian MIDI System driver",       "?",
  532.     RESERVED,                 "TCDE", "?",                                                    "Merging Technologies",
  533.     RKM | CD,                 "TDDD", "3D rendering data (Turbo Silver)",                     "Impulse",
  534.     UNREGISTERED,             "TERM", "?",                                                    "?",
  535.     CD,                       "TMUI", "ToolMaker User Interface",                             "Michael Erwin",
  536.     CD,                       "TREE", "Arbitrary data structures as trees (or nested lists)", "Stefan Reisner",
  537.     CD | PROPOSAL,            "TRKR", "TRacKeR style music module",                           "Full Tilt Entertainment",
  538.     RESERVED,                 "USCR", "Uhuru SCoRe",                                          "EA",
  539.     RESERVED,                 "UVOX", "Uhuru Macintosh VOiXe",                                "EA",
  540.     PRIVATE,                  "VDEO", "Deluxe ViDEO",                                         "EA",
  541.     RKM | CD,                 "WORD", "ProWrite document",                                    "New Horizons Software",
  542.     CD,                       "YUVN", "For storage of Y:U:V image data",                      "MacroSystem"
  543. };
  544.  
  545. AGLOBAL void iff1(void)
  546. {   struct Hook Hook6Struct;
  547.     STRPTR      stringptr;
  548.  
  549.     InitHook(&Hook6Struct, Hook6Func, NULL);
  550.  
  551.     /* Create the window object. */
  552.     lockscreen();
  553.  
  554. if (!(WinObject[6] =
  555. NewObject
  556. (   WINDOW_GetClass(),                    NULL,
  557.     WA_PubScreen,                         ScreenPtr,
  558.     WA_ScreenTitle,                       "Report+",
  559.     WA_Title,                             "Report+: IFF FORM Viewer",
  560.     WA_Activate,                          TRUE,
  561.     WA_DepthGadget,                       TRUE,
  562.     WA_DragBar,                           TRUE,
  563.     WA_CloseGadget,                       TRUE,
  564.     WA_SizeGadget,                        TRUE,
  565.     WA_IDCMP,                             IDCMP_RAWKEY,
  566.     WINDOW_IDCMPHook,                     &Hook6Struct,
  567.     WINDOW_IDCMPHookBits,                 IDCMP_RAWKEY,
  568.     WINDOW_MenuStrip,                     MenuPtr,
  569.     WINDOW_Position,                      WPOS_CENTERSCREEN,
  570.     WINDOW_ParentGroup,                   iff_gadgets[GID_6_LY1] =
  571.     NewObject
  572.     (   LAYOUT_GetClass(),                NULL,
  573.         LAYOUT_Orientation,               LAYOUT_ORIENT_VERT,
  574.         LAYOUT_SpaceOuter,                TRUE,
  575.         LAYOUT_DeferLayout,               TRUE,
  576.         LAYOUT_AddChild,
  577.         NewObject
  578.         (   LAYOUT_GetClass(),            NULL,
  579.             LAYOUT_Orientation,           LAYOUT_ORIENT_HORIZ,
  580.             LAYOUT_DeferLayout,           TRUE,
  581.             LAYOUT_BevelStyle,            BVS_NONE,
  582.             LAYOUT_AddChild,
  583.             NewObject
  584.             (   LAYOUT_GetClass(),        NULL,
  585.                 LAYOUT_Orientation,       LAYOUT_ORIENT_VERT,
  586.                 LAYOUT_VertAlignment,     LALIGN_CENTER,
  587.                 LAYOUT_BevelStyle,        BVS_NONE,
  588.                 LAYOUT_AddChild,
  589.                 NewObject
  590.                 (   LAYOUT_GetClass(),    NULL,
  591.                     LAYOUT_Orientation,   LAYOUT_ORIENT_HORIZ,
  592.                     LAYOUT_HorizAlignment,LALIGN_RIGHT,
  593.                     LAYOUT_BevelStyle,    BVS_NONE,
  594.                     LAYOUT_AddImage,
  595.                     NewObject
  596.                     (   LABEL_GetClass(),     NULL,
  597.                         LABEL_Text,           "_FORM ID:",
  598.                         LABEL_Justification,  LJ_RIGHT,
  599.                     TAG_END),
  600.                 TAG_END),
  601.                 LAYOUT_AddChild,
  602.                 NewObject
  603.                 (   LAYOUT_GetClass(),        NULL,
  604.                     LAYOUT_Orientation,       LAYOUT_ORIENT_HORIZ,
  605.                     LAYOUT_HorizAlignment,    LALIGN_RIGHT,
  606.                     LAYOUT_BevelStyle,        BVS_NONE,
  607.                     LAYOUT_AddImage,
  608.                     NewObject
  609.                     (   LABEL_GetClass(),     NULL,
  610.                         LABEL_Text,           "Description:",
  611.                         LABEL_Justification,  LJ_RIGHT,
  612.                     TAG_END),
  613.                 TAG_END),
  614.                 LAYOUT_AddChild,
  615.                 NewObject
  616.                 (   LAYOUT_GetClass(),        NULL,
  617.                     LAYOUT_Orientation,       LAYOUT_ORIENT_HORIZ,
  618.                     LAYOUT_HorizAlignment,    LALIGN_RIGHT,
  619.                     LAYOUT_BevelStyle,        BVS_NONE,
  620.                     LAYOUT_AddImage,
  621.                     NewObject
  622.                     (   LABEL_GetClass(),     NULL,
  623.                         LABEL_Text,           "Contributor:",
  624.                         LABEL_Justification,  LJ_RIGHT,
  625.                     TAG_END),
  626.                 TAG_END),
  627.                 LAYOUT_AddChild,
  628.                 NewObject
  629.                 (   LAYOUT_GetClass(),        NULL,
  630.                     LAYOUT_Orientation,       LAYOUT_ORIENT_HORIZ,
  631.                     LAYOUT_HorizAlignment,    LALIGN_RIGHT,
  632.                     LAYOUT_BevelStyle,        BVS_NONE,
  633.                     LAYOUT_AddImage,
  634.                     NewObject
  635.                     (   LABEL_GetClass(),     NULL,
  636.                         LABEL_Text,           "Chunk info:",
  637.                         LABEL_Justification,  LJ_RIGHT,
  638.                     TAG_END),
  639.                 TAG_END),
  640.                 LAYOUT_AddChild,
  641.                 NewObject
  642.                 (   LAYOUT_GetClass(),        NULL,
  643.                     LAYOUT_Orientation,       LAYOUT_ORIENT_HORIZ,
  644.                     LAYOUT_HorizAlignment,    LALIGN_RIGHT,
  645.                     LAYOUT_BevelStyle,        BVS_NONE,
  646.                     LAYOUT_AddImage,
  647.                     NewObject
  648.                     (   LABEL_GetClass(),     NULL,
  649.                         LABEL_Text,           "_Pathname:",
  650.                         LABEL_Justification,  LJ_RIGHT,
  651.                     TAG_END),
  652.                 TAG_END),
  653.                 LAYOUT_AddChild,
  654.                 NewObject
  655.                 (   LAYOUT_GetClass(),        NULL,
  656.                     LAYOUT_Orientation,       LAYOUT_ORIENT_HORIZ,
  657.                     LAYOUT_HorizAlignment,    LALIGN_RIGHT,
  658.                     LAYOUT_BevelStyle,        BVS_NONE,
  659.                     LAYOUT_AddImage,
  660.                     NewObject
  661.                     (   LABEL_GetClass(),     NULL,
  662.                         LABEL_Text,           "Status:",
  663.                         LABEL_Justification,  LJ_RIGHT,
  664.                     TAG_END),
  665.                 TAG_END),
  666.             TAG_END),
  667.             CHILD_WeightedWidth,          0,
  668.             LAYOUT_AddChild,
  669.             NewObject
  670.             (   LAYOUT_GetClass(),        NULL,
  671.                 LAYOUT_Orientation,       LAYOUT_ORIENT_VERT,
  672.                 LAYOUT_VertAlignment,     LALIGN_CENTER,
  673.                 LAYOUT_HorizAlignment,    LALIGN_CENTER,
  674.                 LAYOUT_BevelStyle,        BVS_NONE,
  675.                 LAYOUT_AddChild,
  676.                 NewObject
  677.                 (   LAYOUT_GetClass(),    NULL,
  678.                     LAYOUT_Orientation,   LAYOUT_ORIENT_HORIZ,
  679.                     LAYOUT_VertAlignment, LALIGN_CENTER,
  680.                     LAYOUT_HorizAlignment,LALIGN_LEFT,
  681.                     LAYOUT_BevelStyle,    BVS_NONE,
  682.                     LAYOUT_AddChild,          iff_gadgets[GID_6_ST1] =
  683.                     NewObject
  684.                     (   STRING_GetClass(),    NULL,
  685.                         GA_ID,                GID_6_ST1,
  686.                         GA_TabCycle,          TRUE,
  687.                         GA_RelVerify,         TRUE,
  688.                         STRINGA_TextVal,      queryform,
  689.                         STRINGA_ReplaceMode,  TRUE,
  690.                         STRINGA_MinVisible,   4,
  691.                         STRINGA_MaxChars,     4 + 1,
  692.                     TAG_END),
  693.                     CHILD_WeightedWidth,      50,
  694.                     LAYOUT_AddChild,          iff_gadgets[GID_6_CB1] =
  695.                     NewObject
  696.                     (   CHECKBOX_GetClass(),  NULL,
  697.                         GA_ID,                GID_6_CB1,
  698.                         GA_RelVerify,         TRUE,
  699.                         GA_Text,              "_Raw view only?",
  700.                         GA_Selected,          (BOOL) iff.raw,
  701.                     TAG_END),
  702.                     CHILD_WeightedWidth,      50,
  703.                 TAG_END),    
  704.                 LAYOUT_AddChild,          iff_gadgets[GID_6_ST2] =
  705.                 NewObject
  706.                 (   STRING_GetClass(),    NULL,
  707.                     GA_ID,                GID_6_ST2,
  708.                     GA_ReadOnly,          TRUE,
  709.                     STRINGA_TextVal,      "-",
  710.                     STRINGA_MinVisible,   20,
  711.                 TAG_END),
  712.                 LAYOUT_AddChild,          iff_gadgets[GID_6_ST3] =
  713.                 NewObject
  714.                 (   STRING_GetClass(),    NULL,
  715.                     GA_ID,                GID_6_ST3,
  716.                     GA_ReadOnly,          TRUE,
  717.                     STRINGA_TextVal,      "-",
  718.                     STRINGA_MinVisible,   20,
  719.                 TAG_END),
  720.                 LAYOUT_AddChild,          iff_gadgets[GID_6_ST4] =
  721.                 NewObject
  722.                 (   STRING_GetClass(),    NULL,
  723.                     GA_ID,                GID_6_ST4,
  724.                     GA_ReadOnly,          TRUE,
  725.                     STRINGA_TextVal,      "-",
  726.                     STRINGA_MinVisible,   20,
  727.                 TAG_END),
  728.                 LAYOUT_AddChild,
  729.                 NewObject
  730.                 (   LAYOUT_GetClass(),    NULL,
  731.                     LAYOUT_Orientation,   LAYOUT_ORIENT_HORIZ,
  732.                     LAYOUT_VertAlignment, LALIGN_CENTER,
  733.                     LAYOUT_HorizAlignment,LALIGN_LEFT,
  734.                     LAYOUT_BevelStyle,    BVS_NONE,
  735.                     LAYOUT_AddChild,          iff_gadgets[GID_6_ST6] =
  736.                     NewObject
  737.                     (   STRING_GetClass(),    NULL,
  738.                         GA_ID,                GID_6_ST6,
  739.                         GA_RelVerify,         TRUE,
  740.                         GA_TabCycle,          TRUE,
  741.                         STRINGA_TextVal,      iff.pathname,
  742.                         STRINGA_MinVisible,   20,
  743.                         STRINGA_MaxChars,     PATHNAMEFIELD,
  744.                     TAG_END),
  745.                     LAYOUT_AddChild,      iff_gadgets[GID_6_BU1] =
  746.                     NewObject
  747.                     (   NULL,             "button.gadget",
  748.                         GA_ID,            GID_6_BU1,
  749.                         GA_RelVerify,     TRUE,
  750.                         BUTTON_AutoButton,BAG_POPFILE,
  751.                     TAG_END),
  752.                     CHILD_WeightedWidth,  0,
  753.                 TAG_END),
  754.                 CHILD_WeightedHeight,     0,
  755.                 LAYOUT_AddChild,          iff_gadgets[GID_6_ST5] =
  756.                 NewObject
  757.                 (   STRING_GetClass(),    NULL,
  758.                     GA_ID,                GID_6_ST5,
  759.                     GA_ReadOnly,          TRUE,
  760.                     STRINGA_TextVal,      "Ready.",
  761.                     STRINGA_MinVisible,   20,
  762.                 TAG_END),
  763.             TAG_END),
  764.             CHILD_WeightedWidth,          100,
  765.             LAYOUT_AddChild,
  766.             NewObject
  767.             (   LAYOUT_GetClass(),        NULL,
  768.                 LAYOUT_Orientation,       LAYOUT_ORIENT_VERT,
  769.                 LAYOUT_SpaceOuter,        TRUE,
  770.                 LAYOUT_VertAlignment,     LALIGN_CENTER,
  771.                 LAYOUT_HorizAlignment,    LALIGN_LEFT,
  772.                 LAYOUT_BevelStyle,        BVS_FIELD,
  773.                 LAYOUT_AddImage,
  774.                 NewObject
  775.                 (   LABEL_GetClass(),     NULL,
  776.                     LABEL_Text,           "FORM Status:",
  777.                     LABEL_Justification,  LJ_RIGHT,
  778.                 TAG_END),
  779.                 LAYOUT_AddChild,          iff_gadgets[GID_6_CB2] =
  780.                 NewObject
  781.                 (   CHECKBOX_GetClass(),  NULL,
  782.                     GA_ID,                GID_6_CB2,
  783.                     GA_Disabled,          TRUE,
  784.                     GA_Text,              "Obsolete?",
  785.                     GA_Selected,          (BOOL) iff.obsolete,
  786.                 TAG_END),
  787.                 LAYOUT_AddChild,          iff_gadgets[GID_6_CB3] =
  788.                 NewObject
  789.                 (   CHECKBOX_GetClass(),  NULL,
  790.                     GA_ID,                GID_6_CB3,
  791.                     GA_Disabled,          TRUE,
  792.                     GA_Text,              "Private?",
  793.                     GA_Selected,          (BOOL) iff.private,
  794.                 TAG_END),
  795.                 LAYOUT_AddChild,          iff_gadgets[GID_6_CB4] =
  796.                 NewObject
  797.                 (   CHECKBOX_GetClass(),  NULL,
  798.                     GA_ID,                GID_6_CB4,
  799.                     GA_Disabled,          TRUE,
  800.                     GA_Text,              "Proposal?",
  801.                     GA_Selected,          (BOOL) iff.proposal,
  802.                 TAG_END),
  803.                 LAYOUT_AddChild,          iff_gadgets[GID_6_CB5] =
  804.                 NewObject
  805.                 (   CHECKBOX_GetClass(),  NULL,
  806.                     GA_ID,                GID_6_CB5,
  807.                     GA_Disabled,          TRUE,
  808.                     GA_Text,              "Reserved?",
  809.                     GA_Selected,          (BOOL) iff.reserved,
  810.                 TAG_END),
  811.                 LAYOUT_AddChild,          iff_gadgets[GID_6_CB6] =
  812.                 NewObject
  813.                 (   CHECKBOX_GetClass(),  NULL,
  814.                     GA_ID,                GID_6_CB6,
  815.                     GA_Disabled,          TRUE,
  816.                     GA_Text,              "Standard?",
  817.                     GA_Selected,          (BOOL) iff.standard,
  818.                 TAG_END),
  819.                 LAYOUT_AddChild,          iff_gadgets[GID_6_CB7] =
  820.                 NewObject
  821.                 (   CHECKBOX_GetClass(),  NULL,
  822.                     GA_ID,                GID_6_CB7,
  823.                     GA_Disabled,          TRUE,
  824.                     GA_Text,              "Unregistered?",
  825.                     GA_Selected,          (BOOL) iff.unregistered,
  826.                 TAG_END),
  827.             TAG_END),
  828.             CHILD_WeightedWidth,          0,
  829.         TAG_END),
  830.         CHILD_WeightedHeight,             0,
  831.         LAYOUT_AddChild,
  832.         NewObject
  833.         (   LAYOUT_GetClass(),            NULL,
  834.             LAYOUT_Orientation,           LAYOUT_ORIENT_HORIZ,
  835.             LAYOUT_HorizAlignment,        LALIGN_CENTER,
  836.             LAYOUT_BevelStyle,            BVS_NONE,
  837.             LAYOUT_AddChild,
  838.             NewObject
  839.             (   LAYOUT_GetClass(),        NULL,
  840.                 LAYOUT_Orientation,       LAYOUT_ORIENT_VERT,
  841.                 LAYOUT_HorizAlignment,    LALIGN_CENTER,
  842.                 LAYOUT_BevelStyle,        BVS_NONE,
  843.                 LAYOUT_AddImage,
  844.                 NewObject
  845.                 (   LABEL_GetClass(),     NULL,
  846.                     LABEL_Text,           "Chunks:",
  847.                     LABEL_Justification,  LJ_CENTER,
  848.                 TAG_END),
  849.                 CHILD_WeightedHeight,     0,
  850.                 LAYOUT_AddChild,          iff_gadgets[GID_6_LB1] =
  851.                 NewObject
  852.                 (   LISTBROWSER_GetClass(),NULL,
  853.                     GA_ID,                 GID_6_LB1,
  854.                     GA_RelVerify,          TRUE,
  855.                     GA_TextAttr,           &Topaz8,
  856.                     LISTBROWSER_Labels,    (ULONG) &List1,
  857.                 TAG_END),
  858.                 CHILD_MinWidth,            140,
  859.             TAG_END),
  860.             CHILD_WeightedWidth,           100,
  861.             LAYOUT_AddChild,
  862.             NewObject
  863.             (   LAYOUT_GetClass(),        NULL,
  864.                 LAYOUT_Orientation,       LAYOUT_ORIENT_VERT,
  865.                 LAYOUT_HorizAlignment,    LALIGN_CENTER,
  866.                 LAYOUT_BevelStyle,        BVS_NONE,
  867.                 LAYOUT_AddImage,
  868.                 NewObject
  869.                 (   LABEL_GetClass(),     NULL,
  870.                     LABEL_Text,           "Chunk contents:",
  871.                     LABEL_Justification,  LJ_CENTER,
  872.                 TAG_END),
  873.                 CHILD_WeightedHeight,     0,
  874.                 LAYOUT_AddChild,          iff_gadgets[GID_6_LB2] =
  875.                 NewObject
  876.                 (   LISTBROWSER_GetClass(),NULL,
  877.                     GA_ID,                 GID_6_LB2,
  878.                     GA_RelVerify,          TRUE,
  879.                     GA_TextAttr,           &Topaz8,
  880.                     LISTBROWSER_Labels,    (ULONG) &List2,
  881.                 TAG_END),
  882.                 CHILD_MinWidth,           456,
  883.                 CHILD_MaxWidth,           456,
  884.             TAG_END),
  885.             CHILD_WeightedWidth,          0,
  886.         TAG_END),
  887.         CHILD_WeightedHeight,             100,
  888.         CHILD_MinHeight,                  160,
  889.         LAYOUT_AddChild,
  890.         NewObject
  891.         (   LAYOUT_GetClass(),        NULL,
  892.             LAYOUT_Orientation,       LAYOUT_ORIENT_HORIZ,
  893.             LAYOUT_HorizAlignment,    LALIGN_RIGHT,
  894.             LAYOUT_VertAlignment,     LALIGN_CENTER,
  895.             LAYOUT_BevelStyle,        BVS_NONE,
  896.             LAYOUT_AddImage,
  897.             NewObject
  898.             (   LABEL_GetClass(),     NULL,
  899.                 LABEL_Text,           "Documents:",
  900.                 LABEL_Justification,  LJ_RIGHT,
  901.             TAG_END),
  902.             CHILD_WeightedWidth,      0,
  903.             LAYOUT_AddChild,          iff_gadgets[GID_6_CB8] =
  904.             NewObject
  905.             (   CHECKBOX_GetClass(),  NULL,
  906.                 GA_ID,                GID_6_CB8,
  907.                 GA_Disabled,          TRUE,
  908.                 GA_Text,              "RKM?",
  909.                 GA_Selected,          (BOOL) iff.rkm,
  910.             TAG_END),
  911.             CHILD_WeightedWidth,      0,
  912.             LAYOUT_AddChild,          iff_gadgets[GID_6_CB9] =
  913.             NewObject
  914.             (   CHECKBOX_GetClass(),  NULL,
  915.                 GA_ID,                GID_6_CB9,
  916.                 GA_Disabled,          TRUE,
  917.                 GA_Text,              "ADCD 2.1?",
  918.                 GA_Selected,          (BOOL) iff.cd,
  919.             TAG_END),
  920.             CHILD_WeightedWidth,       0,
  921.             LAYOUT_AddImage,           NewObject
  922.             (   LABEL_GetClass(),      NULL,
  923.                 LABEL_Text,            "",
  924.             TAG_END),
  925.             CHILD_WeightedWidth,       100,
  926.         TAG_END),
  927.         CHILD_WeightedHeight,          0,
  928.     TAG_END),
  929. TAG_END)))
  930. {   rq("Can't create ReAction gadgets!");
  931. }
  932. unlockscreen();
  933. openwindow();
  934.  
  935.     if (iff.pathname[0])
  936.     {   readiff();
  937.     } elif (queryform[0])
  938.     {   iffquery();
  939.     }
  940.  
  941.     ActivateLayoutGadget(iff_gadgets[GID_6_LY1], MainWindowPtr, NULL, (Object) iff_gadgets[GID_6_ST6]);
  942.  
  943.     loop();
  944.  
  945.     if (!(GetAttr
  946.     (   STRINGA_TextVal, iff_gadgets[GID_6_ST1], (ULONG *) &stringptr
  947.     )))
  948.     {   rq("Unsupported inquiry!"); // should never happen
  949.     }
  950.     strcpy(queryform, stringptr);
  951.  
  952.     if (!(GetAttr
  953.     (   STRINGA_TextVal, iff_gadgets[GID_6_ST6], (ULONG *) &stringptr
  954.     )))
  955.     {   rq("Unsupported inquiry!"); // should never happen
  956.     }
  957.     strcpy(iff.pathname, stringptr);
  958.  
  959.     closewindow();
  960.     // now that the window is closed we can free lists
  961.     iff_exit();
  962. }
  963.  
  964. AGLOBAL void iff_loop(ULONG gid)
  965. {   STRPTR stringptr;
  966.     ULONG  code;
  967.  
  968.     switch(gid)
  969.     {
  970.     case GID_6_CB1:
  971.         if (!(GetAttr
  972.         (   GA_Selected, iff_gadgets[GID_6_CB1], (ULONG *) &iff.raw
  973.         )))
  974.         {   rq("Unsupported inquiry!"); // should never happen
  975.         }
  976.         if (selectedchunk && known)
  977.         {   tellchunk(selectedchunk);
  978.         }
  979.     break;
  980.     case GID_6_ST1:
  981.         if (!(GetAttr
  982.         (   STRINGA_TextVal, iff_gadgets[GID_6_ST1], (ULONG *) &stringptr
  983.         )))
  984.         {   rq("Unsupported inquiry!"); // should never happen
  985.         }
  986.         strcpy(queryform, stringptr);
  987.  
  988.         iff.pathname[0] = 0;
  989.         SetGadgetAttrs
  990.         (   iff_gadgets[GID_6_ST6],
  991.             MainWindowPtr, NULL,
  992.             STRINGA_TextVal, iff.pathname,
  993.             TAG_END
  994.         );
  995.         SetGadgetAttrs
  996.         (   iff_gadgets[GID_6_ST5],
  997.             MainWindowPtr, NULL,
  998.             STRINGA_TextVal, "Ready.",
  999.             TAG_END
  1000.         );
  1001.         iffquery();
  1002.     break;
  1003.     case GID_6_ST6:
  1004.         if (!(GetAttr
  1005.         (   STRINGA_TextVal, iff_gadgets[GID_6_ST6], (ULONG *) &stringptr
  1006.         )))
  1007.         {   rq("Unsupported inquiry!"); // should never happen
  1008.         }
  1009.         strcpy(iff.pathname, stringptr);
  1010.         readiff();
  1011.     break;
  1012.     case GID_6_BU1:
  1013.         if (asl("~(#?.info)"))
  1014.         {   strcpy(iff.pathname, aslresult);
  1015.             SetGadgetAttrs
  1016.             (   iff_gadgets[GID_6_ST6],
  1017.                 MainWindowPtr, NULL,
  1018.                 STRINGA_TextVal, iff.pathname,
  1019.                 TAG_END
  1020.             );
  1021.             readiff();
  1022.         }
  1023.     break;
  1024.     case GID_6_LB1:
  1025.         /* code is the position within the list, starting from 0. */
  1026.  
  1027.         if (!(GetAttr
  1028.         (   LISTBROWSER_Selected, iff_gadgets[GID_6_LB1], (ULONG *) &code
  1029.         )))
  1030.         {   rq("Unsupported inquiry!"); // should never happen
  1031.         }
  1032.         selectedchunk = code + 1;
  1033.         tellchunk(selectedchunk);
  1034.     break;
  1035.     default:
  1036.     break;
  1037. }   }
  1038.  
  1039. MODULE void iffquery(void)
  1040. {   ULONG i;
  1041.  
  1042.     /* Make any corrections to input now, to make it
  1043.     easier to search the database. */
  1044.     for (i = 0; i <= 3; i++)
  1045.         if (queryform[i] >= 97 && queryform[i] <= 122)
  1046.             queryform[i] -= 32;
  1047.         elif (queryform[i] == 0)
  1048.             queryform[i] = ' ';
  1049.     queryform[4] = 0;
  1050.  
  1051.     SetGadgetAttrs
  1052.     (   iff_gadgets[GID_6_ST1],
  1053.         MainWindowPtr, NULL,
  1054.         STRINGA_TextVal, queryform,
  1055.         TAG_END
  1056.     );
  1057.  
  1058.     selectedform = (UWORD) -1;
  1059.     for (i = 0; i <= FORMS; i++)
  1060.     if
  1061.     (   queryform[0] == form[i].name[0]
  1062.      && queryform[1] == form[i].name[1]
  1063.      && queryform[2] == form[i].name[2]
  1064.      && queryform[3] == form[i].name[3]
  1065.     )
  1066.     {   selectedform = i;
  1067.         break;
  1068.     }
  1069.     selectedchunk = 0;
  1070.     if (selectedform == (UWORD) -1)
  1071.     {   iff.cd           =
  1072.         iff.rkm          =
  1073.         iff.private      =
  1074.         iff.proposal     =
  1075.         iff.obsolete     =
  1076.         iff.reserved     =
  1077.         iff.standard     =
  1078.         iff.unregistered = FALSE;
  1079.  
  1080.         SetGadgetAttrs
  1081.         (   iff_gadgets[GID_6_ST2],
  1082.             MainWindowPtr, NULL,
  1083.             STRINGA_TextVal, "-",
  1084.             TAG_END
  1085.         );
  1086.         SetGadgetAttrs
  1087.         (   iff_gadgets[GID_6_ST3],
  1088.             MainWindowPtr, NULL,
  1089.             STRINGA_TextVal, "-",
  1090.             TAG_END
  1091.         );
  1092.     } else
  1093.     {   iff.cd           = form[selectedform].flags & CD;
  1094.         iff.rkm          = form[selectedform].flags & RKM;
  1095.         iff.private      = form[selectedform].flags & PRIVATE;
  1096.         iff.proposal     = form[selectedform].flags & PROPOSAL;
  1097.         iff.obsolete     = form[selectedform].flags & OBSOLETE;
  1098.         iff.reserved     = form[selectedform].flags & RESERVED;
  1099.         iff.standard     = form[selectedform].flags & STANDARD;
  1100.         iff.unregistered = form[selectedform].flags & UNREGISTERED;
  1101.  
  1102.         SetGadgetAttrs
  1103.         (   iff_gadgets[GID_6_ST2],
  1104.             MainWindowPtr, NULL,
  1105.             STRINGA_TextVal, form[selectedform].desc,
  1106.             TAG_END
  1107.         );
  1108.         SetGadgetAttrs
  1109.         (   iff_gadgets[GID_6_ST3],
  1110.             MainWindowPtr, NULL,
  1111.             STRINGA_TextVal, form[selectedform].contributor,
  1112.             TAG_END
  1113.         );
  1114.     }
  1115.  
  1116.     writeiffgadgets();
  1117.  
  1118.     SetGadgetAttrs
  1119.     (   iff_gadgets[GID_6_LB1],
  1120.         MainWindowPtr, NULL,
  1121.         LISTBROWSER_Labels, NULL, // detach it
  1122.         TAG_END
  1123.     );
  1124.     clearreactionlist(&List1);
  1125.  
  1126.     SetGadgetAttrs
  1127.     (   iff_gadgets[GID_6_LB2],
  1128.         MainWindowPtr, NULL,
  1129.         LISTBROWSER_Labels, NULL, // detach it
  1130.         TAG_END
  1131.     );
  1132.     clearreactionlist(&List2);
  1133.  
  1134.     for (i = 0; i < items; i++)
  1135.     {   if (contents[i].DataPtr)
  1136.         {   FreeMem(contents[i].DataPtr, contents[i].bytes);
  1137.             contents[i].DataPtr = NULL;
  1138.     }   }
  1139.     items = 0;
  1140. }
  1141.  
  1142. MODULE void readiff(void)
  1143. {   LONG error;
  1144.  
  1145.     iffquery();
  1146.  
  1147.     /* Allocate IFF_File structure. */
  1148.     if (!(IFFHandle = AllocIFF()))
  1149.     {   DisplayBeep(NULL);
  1150.         SetGadgetAttrs
  1151.         (   iff_gadgets[GID_6_ST5],
  1152.             MainWindowPtr, NULL,
  1153.             STRINGA_TextVal, "AllocIFF() failed!",
  1154.             TAG_END
  1155.         );
  1156.  
  1157.         goto bye;
  1158.     }
  1159.  
  1160.     first = TRUE;
  1161.  
  1162.     /* Set up IFF_File for AmigaDOS I/O.  */
  1163.     if (!(IFFHandle->iff_Stream = Open(iff.pathname, MODE_OLDFILE)))
  1164.     {   DisplayBeep(NULL);
  1165.         SetGadgetAttrs
  1166.         (   iff_gadgets[GID_6_ST5],
  1167.             MainWindowPtr, NULL,
  1168.             STRINGA_TextVal, "Can't open file!",
  1169.             TAG_END
  1170.         );
  1171.         SetGadgetAttrs
  1172.         (   iff_gadgets[GID_6_ST2],
  1173.             MainWindowPtr, NULL,
  1174.             STRINGA_TextVal, "-",
  1175.             TAG_END
  1176.         );
  1177.         SetGadgetAttrs
  1178.         (   iff_gadgets[GID_6_ST3],
  1179.             MainWindowPtr, NULL,
  1180.             STRINGA_TextVal, "-",
  1181.             TAG_END
  1182.         );
  1183.  
  1184.         queryform[0]     = 0;
  1185.         iff.obsolete     =
  1186.         iff.private      =
  1187.         iff.proposal     =
  1188.         iff.reserved     =
  1189.         iff.standard     =
  1190.         iff.unregistered =
  1191.         iff.rkm          =
  1192.         iff.cd           = FALSE;
  1193.         writeiffgadgets();
  1194.         goto bye;
  1195.     }
  1196.     InitIFFasDOS(IFFHandle);
  1197.  
  1198.     /* Start the IFF transaction. */
  1199.     if (error = OpenIFF(IFFHandle, IFFF_READ))
  1200.     {   DisplayBeep(NULL);
  1201.         SetGadgetAttrs
  1202.         (   iff_gadgets[GID_6_ST5],
  1203.             MainWindowPtr, NULL,
  1204.             STRINGA_TextVal, "OpenIFF() failed!",
  1205.             TAG_END
  1206.         );
  1207.         goto bye;
  1208.     }
  1209.  
  1210.     while (1)
  1211.     {   /* IFFPARSE_RAWSTEP permits us to have precision monitoring of the
  1212.          * parsing process, which is necessary if we wish to print the
  1213.          * structure of an IFF file.
  1214.          *   ParseIFF() with _RAWSTEP will return the following things for
  1215.          * the following reasons:
  1216.          *
  1217.          * Return code:                 Reason:
  1218.          * 0                            Entered new context.
  1219.          * IFFERR_EOC                   About to leave a context.
  1220.          * IFFERR_EOF                   Encountered end-of-file.
  1221.          * <anything else>              A parsing error.
  1222.          */
  1223.         error = ParseIFF(IFFHandle, IFFPARSE_RAWSTEP);
  1224.  
  1225.         /*
  1226.          * Since we're only interested in when we enter a context, we
  1227.          * "discard" end-of-context (_EOC) events.
  1228.          */
  1229.         if (error == IFFERR_EOC)
  1230.             continue;
  1231.         elif (error)
  1232.         {   // Leave the loop if there is any other error.
  1233.             break;
  1234.         }
  1235.  
  1236.         /* If we get here, error was zero. Print out the current state of
  1237.          * affairs. */
  1238.         PrintTopChunk();
  1239.     }
  1240.  
  1241.     /* If error was IFFERR_EOF, then the parser encountered the end of
  1242.      * the file without problems. Otherwise, we print a diagnostic.
  1243.      */
  1244.     if (error == IFFERR_EOF)
  1245.     {   SetGadgetAttrs
  1246.         (   iff_gadgets[GID_6_ST5],
  1247.             MainWindowPtr, NULL,
  1248.             STRINGA_TextVal, "Ready.",
  1249.             TAG_END
  1250.         );
  1251.         SetGadgetAttrs
  1252.         (   iff_gadgets[GID_6_LB1],
  1253.             MainWindowPtr, NULL,
  1254.             LISTBROWSER_Labels, &List1,
  1255.             TAG_END
  1256.         );
  1257.     } else
  1258.     {   SetGadgetAttrs
  1259.         (   iff_gadgets[GID_6_ST5],
  1260.             MainWindowPtr, NULL,
  1261.             STRINGA_TextVal, errormsgs[-error - 1],
  1262.             TAG_END
  1263.         );
  1264.         SetGadgetAttrs
  1265.         (   iff_gadgets[GID_6_LB1],
  1266.             MainWindowPtr, NULL,
  1267.             LISTBROWSER_Labels, NULL, // detach it
  1268.             TAG_END
  1269.         );
  1270.     }
  1271.  
  1272. bye:
  1273.     if (IFFHandle)
  1274.     {   /* Terminate the IFF transaction with the stream. Free all
  1275.          * associated structures. */
  1276.         CloseIFF(IFFHandle);
  1277.         // Close the stream itself.
  1278.         if (IFFHandle->iff_Stream)
  1279.         {   Close(IFFHandle->iff_Stream);
  1280.         }
  1281.         // Free the IFF_File structure itself.
  1282.         FreeIFF(IFFHandle);
  1283.         IFFHandle = NULL;
  1284. }   }
  1285.  
  1286. AGLOBAL void iff_exit(void)
  1287. {   ULONG i;
  1288.  
  1289.     if (IFFHandle)
  1290.     {   /* Terminate the IFF transaction with the stream. Free all
  1291.          * associated structures. */
  1292.         CloseIFF(IFFHandle);
  1293.         // Close the stream itself.
  1294.         if (IFFHandle->iff_Stream)
  1295.         {   Close(IFFHandle->iff_Stream);
  1296.         }
  1297.         // Free the IFF_File structure itself.
  1298.         FreeIFF(IFFHandle);
  1299.         IFFHandle = NULL;
  1300.     }
  1301.  
  1302.     clearreactionlist(&List2);
  1303.     clearreactionlist(&List1);
  1304.  
  1305.     for (i = 0; i < items; i++)
  1306.     {   if (contents[i].DataPtr)
  1307.         {   FreeMem(contents[i].DataPtr, contents[i].bytes);
  1308.             contents[i].DataPtr = NULL;
  1309.     }   }
  1310.     items = 0;
  1311. }
  1312.  
  1313. MODULE void PrintTopChunk(void)
  1314. {   struct ContextNode* top;
  1315.     short               i;
  1316.     char                idbuf[5];
  1317.     ULONG               length;
  1318.  
  1319.     /* Get a pointer to the context node describing the current context. */
  1320.     if (!(top = CurrentChunk(IFFHandle)))
  1321.         return;
  1322.  
  1323.     /* Print spaces equivalent to the current nesting depth of chunks
  1324.      * processed so far.
  1325.      *   This will cause nested chunks to be printed out indented. */
  1326.  
  1327.     tempstring1[0] = 0;
  1328.     if (IFFHandle->iff_Depth > 2)
  1329.     {   for (i = IFFHandle->iff_Depth - 2; i--; )
  1330.            strcat(tempstring1, " ");
  1331.     }
  1332.     strcpy(contents[items].name, IDtoStr(top->cn_ID, idbuf));
  1333.     contents[items].DataPtr = NULL;
  1334.  
  1335.     /* Print out the current chunk's ID and size. */
  1336.     strcat(tempstring1, IDtoStr(top->cn_ID, idbuf));
  1337.     stcl_d(tempstring2, top->cn_Size);
  1338.  
  1339.     length = IFFXCHARS - strlen(tempstring1) - strlen(tempstring2);
  1340.     for (i = 1; i <= length; i++)
  1341.     {   strcat(tempstring1, " ");
  1342.     }
  1343.     strcat(tempstring1, tempstring2);
  1344.  
  1345.     /* Print the current chunk's type, with a newline. */
  1346.     addreactionnode(&List1, tempstring1);
  1347.  
  1348.     if (!strcmp(IDtoStr(top->cn_ID, idbuf), "FORM"))
  1349.     {   if (first)
  1350.         {   first = FALSE;
  1351.             strcpy(queryform, IDtoStr(top->cn_Type, idbuf));
  1352.             iffquery();
  1353.     }   }
  1354.     else
  1355.     {   contents[items].bytes = top->cn_Size;
  1356.         if (!(contents[items].DataPtr = AllocMem(contents[items].bytes, MEMF_CLEAR)))
  1357.         {   rq("Out of memory!");
  1358.         }
  1359.         if (ReadChunkBytes(IFFHandle, contents[items].DataPtr, contents[items].bytes) < 0)
  1360.         {   rq("ReadChunkBytes() failed!");
  1361.     }   }
  1362.  
  1363.     items++;
  1364.     if (items > ITEMS)
  1365.     {   rq("Too many chunks!");
  1366. }   }
  1367.  
  1368. MODULE void tellchunk(UWORD which)
  1369. {   SLONG           svalue;
  1370.     ULONG           i, j, uvalue, length, markers, currentpos;
  1371.     struct DateTime DateTime;
  1372.  
  1373.     if (which == (UWORD) ~0)
  1374.     {   return;
  1375.     }
  1376.  
  1377.     SetGadgetAttrs
  1378.     (   iff_gadgets[GID_6_LB2],
  1379.         MainWindowPtr, NULL,
  1380.         LISTBROWSER_Labels, NULL, // detach it
  1381.         TAG_END
  1382.     );
  1383.     clearreactionlist(&List2);
  1384.     known = FALSE;
  1385.  
  1386.     if (!stricmp(contents[which].name, "FORM"))
  1387.     {   chunkdesc("-", TRUE);
  1388.     } elif (!stricmp(contents[which].name, "(c) "))
  1389.     {   chunkdesc("© Copyright", TRUE);
  1390.  
  1391.         if (!iff.raw)
  1392.         {   label("© Copyright:");
  1393.             strcat(tempstring1, contents[which].DataPtr);
  1394.             addreactionnode(&List2, tempstring1);
  1395.     }   }
  1396.     elif (!stricmp(contents[which].name, "AUTH"))
  1397.     {   chunkdesc("Author", TRUE);
  1398.  
  1399.         if (!iff.raw)
  1400.         {   label("Author:");
  1401.             strcat(tempstring1, contents[which].DataPtr);
  1402.             addreactionnode(&List2, tempstring1);
  1403.     }   }
  1404.     elif (!stricmp(contents[which].name, "ANNO"))
  1405.     {   chunkdesc("Annotation", TRUE);
  1406.  
  1407.         if (!iff.raw)
  1408.         {   label("Annotation:");
  1409.             strcat(tempstring1, contents[which].DataPtr);
  1410.             addreactionnode(&List2, tempstring1);
  1411.     }   }
  1412.     elif (!stricmp(contents[which].name, "NAME"))
  1413.     {   chunkdesc("Name", TRUE);
  1414.  
  1415.         if (!iff.raw)
  1416.         {   label("Name:");
  1417.             strcat(tempstring1, contents[which].DataPtr);
  1418.             addreactionnode(&List2, tempstring1);
  1419.     }   }
  1420.     elif (!stricmp(contents[which].name, "FVER"))
  1421.     {   chunkdesc("AmigaDOS version string", TRUE);
  1422.  
  1423.         if (!iff.raw)
  1424.         {   label("Version:");
  1425.             // bytes 0-5 are "$VER: "
  1426.             strcat(tempstring1, &contents[which].DataPtr[6]);
  1427.             addreactionnode(&List2, tempstring1);
  1428.     }   }
  1429.     elif
  1430.     (   (!stricmp(queryform, "FTXT") || !stricmp(queryform, "WORD"))
  1431.      && !stricmp(contents[which].name, "FSCC")
  1432.     )
  1433.     {   chunkdesc("Font/style/colour change", TRUE);
  1434.  
  1435.         if (!iff.raw)
  1436.         {   label("Location:");
  1437.             uvalue = getuword(contents[which].DataPtr); // UWORD
  1438.             unumcat(uvalue, TRUE);
  1439.  
  1440.             label("Font number:");
  1441.             uvalue = contents[which].DataPtr[2]; // UBYTE
  1442.             unumcat(uvalue, TRUE);
  1443.  
  1444.             label("Style:");
  1445.             addreactionnode(&List2, tempstring1);
  1446.  
  1447.             label(" Underlined?");
  1448.             dobool(contents[which].DataPtr[3] & 1);
  1449.  
  1450.             label(" Bold?");
  1451.             dobool(contents[which].DataPtr[3] & 2);
  1452.  
  1453.             label(" Italic?");
  1454.             dobool(contents[which].DataPtr[3] & 4);
  1455.  
  1456.             label(" Extended?");
  1457.             dobool(contents[which].DataPtr[3] & 8);
  1458.  
  1459.             label(" ColourFont?");
  1460.             dobool(contents[which].DataPtr[3] & 64);
  1461.  
  1462.             label(" Tagged?");
  1463.             dobool(contents[which].DataPtr[3] & 128);
  1464.  
  1465.             label("Miscellaneous style:");
  1466.             interpret(1, (ULONG) contents[which].DataPtr[4]);
  1467.  
  1468.             label("Colour:");
  1469.             uvalue = contents[which].DataPtr[5]; // UBYTE
  1470.             unumcat(uvalue, TRUE);
  1471.     }   }
  1472.     elif (!strcmp(queryform, "FTXT"))
  1473.     {   if (!strcmp(contents[which].name, "FONS"))
  1474.         {   chunkdesc("Font specifier", TRUE);
  1475.  
  1476.         if (!iff.raw)
  1477.         {
  1478.             label("ID number:");
  1479.             snumcat((SLONG) contents[which].DataPtr[0], FALSE);
  1480.             if (contents[which].DataPtr[0] > 9)
  1481.             {   strcat(tempstring1, " (invalid)");
  1482.             }
  1483.             addreactionnode(&List2, tempstring1);
  1484.  
  1485.             // Next is a pad byte ([1]).
  1486.  
  1487.             label("Proportional?");
  1488.             interpret(2, (ULONG) contents[which].DataPtr[2]);
  1489.  
  1490.             label("Serifs?");
  1491.             interpret(2, (ULONG) contents[which].DataPtr[3]);
  1492.  
  1493.             label("Font name:");
  1494.             strcat(tempstring1, &(contents[which].DataPtr[4]));
  1495.             addreactionnode(&List2, tempstring1);
  1496.         }   }
  1497.         elif (!strcmp(contents[which].name, "CHRS"))
  1498.         {   chunkdesc("Stream of text", FALSE);
  1499.     }   }
  1500.     elif (!strcmp(queryform, "PREF"))
  1501.     {   if (!strcmp(contents[which].name, "ICTL"))
  1502.         {   chunkdesc("IControl preferences", TRUE);
  1503.  
  1504.         if (!iff.raw)
  1505.         {
  1506.             label("Verify timeout:");
  1507.             uvalue = getuword(&(contents[which].DataPtr[16]));
  1508.             unumcat(uvalue, TRUE);
  1509.  
  1510.             label("Meta drag mouse event:");
  1511.             svalue = getsword(&(contents[which].DataPtr[18]));
  1512.             snumcat(svalue, TRUE);
  1513.  
  1514.             addreactionnode(&List2, "Flags:");
  1515.             uvalue = getulong(&(contents[which].DataPtr[20]));
  1516.  
  1517.             label(" Coerce colours?");
  1518.             dobool((UBYTE) (uvalue & 1)); // ICF_COERCE_COLORS
  1519.  
  1520.             label(" Coerce interlace?");
  1521.             dobool((UBYTE) (uvalue & 2)); // ICF_COERCE_LACE
  1522.  
  1523.             label(" String gadget filter?");
  1524.             dobool((UBYTE) (uvalue & 4)); // ICF_STRGAD_FILTER
  1525.  
  1526.             label(" Menu snap?");
  1527.             dobool((UBYTE) (uvalue & 8)); // ICF_MENUSNAP
  1528.  
  1529.             label(" Mode promotion?");
  1530.             dobool((UBYTE) (uvalue & 16)); // ICF_MODEPROMOTE
  1531.  
  1532.             label(" Square ratio?"); // this one is new for OS3.9
  1533.             dobool((UBYTE) (uvalue & 32)); // ICF_SQUARE_RATIO
  1534.  
  1535.             addreactionnode(&List2, "Command keys:");
  1536.  
  1537.             label(" Workbench to front:");
  1538.             snumcat((SLONG) contents[which].DataPtr[24], TRUE);
  1539.  
  1540.             label(" Front screen to back:");
  1541.             snumcat((SLONG) contents[which].DataPtr[25], TRUE);
  1542.  
  1543.             label(" Requester TRUE:");
  1544.             snumcat((SLONG) contents[which].DataPtr[26], TRUE);
  1545.  
  1546.             label(" Requester FALSE:");
  1547.             snumcat((SLONG) contents[which].DataPtr[27], TRUE);
  1548.         }   }
  1549.         elif (!strcmp(contents[which].name, "SERL"))
  1550.         {   chunkdesc("Serial preferences", TRUE);
  1551.  
  1552.         if (!iff.raw)
  1553.         {
  1554.             label("Unit 0 mapping:");
  1555.             uvalue = getulong(&(contents[which].DataPtr[12]));
  1556.             unumcat(uvalue, TRUE);
  1557.  
  1558.             label("Baud rate:");
  1559.             uvalue = getulong(&(contents[which].DataPtr[16]));
  1560.             unumcat(uvalue, FALSE);
  1561.             strcat(tempstring1, " bps");
  1562.             addreactionnode(&List2, tempstring1);
  1563.  
  1564.             label("Input buffer size:");
  1565.             uvalue = getulong(&(contents[which].DataPtr[20]));
  1566.             unumcat(uvalue, FALSE);
  1567.             if (uvalue > 65536)
  1568.             {   strcat(tempstring1, "!");
  1569.             }
  1570.             addreactionnode(&List2, tempstring1);
  1571.  
  1572.             label("Output buffer size:");
  1573.             uvalue = getulong(&(contents[which].DataPtr[24]));
  1574.             unumcat(uvalue, FALSE);
  1575.             if (uvalue > 65536)
  1576.             {   strcat(tempstring1, "!");
  1577.             }
  1578.             addreactionnode(&List2, tempstring1);
  1579.  
  1580.             label("Input handshaking:");
  1581.             interpret(0, (ULONG) contents[which].DataPtr[28]);
  1582.  
  1583.             label("Output handshaking:");
  1584.             interpret(0, (ULONG) contents[which].DataPtr[29]);
  1585.  
  1586.             label("Parity:");
  1587.             interpret(3, (ULONG) contents[which].DataPtr[30]);
  1588.  
  1589.             label("I/O bits per character:");
  1590.             snumcat((SLONG) contents[which].DataPtr[31], TRUE);
  1591.  
  1592.             label("Stop bits:");
  1593.             snumcat((SLONG) contents[which].DataPtr[32], TRUE);
  1594.         }   }
  1595.         elif (!strcmp(contents[which].name, "ASL "))
  1596.         {   chunkdesc("ASL preferences", TRUE);
  1597.  
  1598.             // 16 reserved bytes at start
  1599.  
  1600.             if (!iff.raw)
  1601.             {   label("Sort by:");
  1602.                 interpret(4, (ULONG) contents[which].DataPtr[16]);
  1603.  
  1604.                 label("Sort drawers:");
  1605.                 interpret(5, (ULONG) contents[which].DataPtr[17]);
  1606.  
  1607.                 label("Sort order:");
  1608.                 interpret(6, (ULONG) contents[which].DataPtr[18]);
  1609.  
  1610.                 label("Override?");
  1611.                 dobool(contents[which].DataPtr[19] & 64);
  1612.  
  1613.                 label("Relative?");
  1614.                 dobool(contents[which].DataPtr[19] & 16);
  1615.  
  1616.                 label("Position:");
  1617.                 interpret(7, (ULONG) contents[which].DataPtr[19] & 16);
  1618.  
  1619.                 label("Left edge:");
  1620.                 svalue = getsword(&(contents[which].DataPtr[20]));
  1621.                 snumcat(svalue, TRUE);
  1622.  
  1623.                 label("Top edge:");
  1624.                 svalue = getsword(&(contents[which].DataPtr[22]));
  1625.                 snumcat(svalue, TRUE);
  1626.  
  1627.                 label("Relative width:");
  1628.                 snumcat((SLONG) contents[which].DataPtr[24], FALSE);
  1629.                 if (contents[which].DataPtr[24] < 25 || contents[which].DataPtr[24] > 100)
  1630.                 {   strcat(tempstring1, "!");
  1631.                 }
  1632.                 strcat(tempstring1, "%");
  1633.                 addreactionnode(&List2, tempstring1);
  1634.  
  1635.                 label("Relative height:");
  1636.                 snumcat((SLONG) contents[which].DataPtr[25], FALSE);
  1637.                 if (contents[which].DataPtr[25] < 25 || contents[which].DataPtr[25] > 100)
  1638.                 {   strcat(tempstring1, "!");
  1639.                 }
  1640.                 strcat(tempstring1, "%");
  1641.                 addreactionnode(&List2, tempstring1);
  1642.         }   }
  1643.         elif (!strcmp(contents[which].name, "FONT"))
  1644.         {   chunkdesc("Font preferences", TRUE);
  1645.  
  1646.             // 14 reserved bytes at start
  1647.  
  1648.         if (!iff.raw)
  1649.         {
  1650.             label("Type:");
  1651.             uvalue = getuword(&(contents[which].DataPtr[14]));
  1652.             interpret(8, uvalue);
  1653.  
  1654.             label("Front pen:");
  1655.             snumcat((SLONG) contents[which].DataPtr[16], TRUE);
  1656.  
  1657.             label("Back pen:");
  1658.             snumcat((SLONG) contents[which].DataPtr[17], TRUE);
  1659.  
  1660.             label("Draw mode:");
  1661.             interpret(9, (ULONG) contents[which].DataPtr[18]);
  1662.  
  1663.             /* Now we have an undocumented pad byte, necessary for
  1664.             structure alignment purposes. */
  1665.  
  1666.             addreactionnode(&List2, "Text attributes:");
  1667.  
  1668.             dotextattr(&contents[which].DataPtr[20]);
  1669.  
  1670.             label("Name:");
  1671.             strcat(tempstring1, &(contents[which].DataPtr[28]));
  1672.             addreactionnode(&List2, tempstring1);
  1673.         }   }
  1674.         elif (!strcmp(contents[which].name, "INPT"))
  1675.         {   chunkdesc("Input preferences", TRUE);
  1676.  
  1677.             // The first 16 bytes are a keymap, currently ignored
  1678.  
  1679.         if (!iff.raw)
  1680.         {
  1681.             label("Pointer sensitivity:");
  1682.             uvalue = getuword(&(contents[which].DataPtr[16]));
  1683.             unumcat(uvalue, FALSE);
  1684.             strcat(tempstring1, " ticks");
  1685.             addreactionnode(&List2, tempstring1);
  1686.  
  1687.             addreactionnode(&List2, "Double-click interval:");
  1688.  
  1689.             label(" Seconds:");
  1690.             uvalue = getulong(&(contents[which].DataPtr[18]));
  1691.             unumcat(uvalue, TRUE);
  1692.  
  1693.             label(" Microseconds:");
  1694.             uvalue = getulong(&(contents[which].DataPtr[22]));
  1695.             unumcat(uvalue, TRUE);
  1696.  
  1697.             addreactionnode(&List2, "Key repeat delay:");
  1698.  
  1699.             label(" Seconds:");
  1700.             uvalue = getulong(&(contents[which].DataPtr[26]));
  1701.             unumcat(uvalue, TRUE);
  1702.  
  1703.             label(" Microseconds:");
  1704.             uvalue = getulong(&(contents[which].DataPtr[30]));
  1705.             unumcat(uvalue, TRUE);
  1706.  
  1707.             addreactionnode(&List2, "Key repeat speed:");
  1708.  
  1709.             label(" Seconds:");
  1710.             uvalue = getulong(&(contents[which].DataPtr[34]));
  1711.             unumcat(uvalue, TRUE);
  1712.  
  1713.             label(" Microseconds:");
  1714.             uvalue = getulong(&(contents[which].DataPtr[38]));
  1715.             unumcat(uvalue, TRUE);
  1716.  
  1717.             label("Mouse acceleration:");
  1718.             svalue = getsword(&(contents[which].DataPtr[42]));
  1719.             snumcat(svalue, TRUE);
  1720.         }   }
  1721.         elif (!strcmp(contents[which].name, "OSCN"))
  1722.         {   chunkdesc("Overscan preferences", TRUE);
  1723.  
  1724.         if (!iff.raw)
  1725.         {
  1726.             label("Magic?");
  1727.             uvalue = getulong(&(contents[which].DataPtr[4]));
  1728.             if (uvalue == 0xFEDCBA89) // OSCAN_MAGIC
  1729.             {   strcat(tempstring1, "Yes");
  1730.             } else
  1731.             {   strcat(tempstring1, "No");
  1732.             }
  1733.             addreactionnode(&List2, tempstring1);
  1734.  
  1735.             label("Horizontal start:");
  1736.             uvalue = getuword(&(contents[which].DataPtr[8]));
  1737.             unumcat(uvalue, TRUE);
  1738.  
  1739.             label("Horizontal stop:");
  1740.             uvalue = getuword(&(contents[which].DataPtr[10]));
  1741.             unumcat(uvalue, TRUE);
  1742.  
  1743.             label("Vertical start:");
  1744.             uvalue = getuword(&(contents[which].DataPtr[12]));
  1745.             unumcat(uvalue, TRUE);
  1746.  
  1747.             label("Vertical stop:");
  1748.             uvalue = getuword(&(contents[which].DataPtr[14]));
  1749.             unumcat(uvalue, TRUE);
  1750.  
  1751.             label("DisplayID:");
  1752.             uvalue = getulong(&(contents[which].DataPtr[16]));
  1753.             unumcat(uvalue, TRUE);
  1754.  
  1755.             label("View offset:");
  1756.             svalue = getsword(&(contents[which].DataPtr[20]));
  1757.             snumcat(svalue, FALSE);
  1758.             strcat(tempstring1, ",");
  1759.             svalue = getsword(&(contents[which].DataPtr[22]));
  1760.             snumcat(svalue, TRUE);
  1761.  
  1762.             label("Text overscan size:");
  1763.             svalue = getsword(&(contents[which].DataPtr[24]));
  1764.             snumcat(svalue, FALSE);
  1765.             strcat(tempstring1, ",");
  1766.             svalue = getsword(&(contents[which].DataPtr[26]));
  1767.             snumcat(svalue, TRUE);
  1768.  
  1769.             addreactionnode(&List2, "Standard overscan size:");
  1770.  
  1771.             label(" Top-left corner:");
  1772.             svalue = getsword(&(contents[which].DataPtr[28]));
  1773.             snumcat(svalue, FALSE);
  1774.             strcat(tempstring1, ",");
  1775.             svalue = getsword(&(contents[which].DataPtr[30]));
  1776.             snumcat(svalue, TRUE);
  1777.  
  1778.             label(" Bottom-right corner:");
  1779.             svalue = getsword(&(contents[which].DataPtr[32]));
  1780.             snumcat(svalue, FALSE);
  1781.             strcat(tempstring1, ",");
  1782.             svalue = getsword(&(contents[which].DataPtr[34]));
  1783.             snumcat(svalue, TRUE);
  1784.         }   }
  1785.         elif (!strcmp(contents[which].name, "SCRM"))
  1786.         {   chunkdesc("Screen mode preferences", TRUE);
  1787.  
  1788.         if (!iff.raw)
  1789.         {
  1790.             label("DisplayID:");
  1791.             uvalue = getulong(&(contents[which].DataPtr[16]));
  1792.             unumcat(uvalue, TRUE);
  1793.  
  1794.             label("Screen width:");
  1795.             uvalue = getuword(&(contents[which].DataPtr[20]));
  1796.             unumcat(uvalue, TRUE);
  1797.  
  1798.             label("Screen height:");
  1799.             uvalue = getuword(&(contents[which].DataPtr[22]));
  1800.             unumcat(uvalue, TRUE);
  1801.  
  1802.             label("Screen depth:");
  1803.             uvalue = getuword(&(contents[which].DataPtr[24]));
  1804.             unumcat(uvalue, TRUE);
  1805.  
  1806.             label("Autoscroll?");
  1807.             uvalue = getuword(&(contents[which].DataPtr[26]));
  1808.             dobool((UBYTE) (uvalue & 1)); // SMB_AUTOSCROLL
  1809.         }   }
  1810.         elif (!strcmp(contents[which].name, "PSPD"))
  1811.         {   chunkdesc("PostScript printer preferences", TRUE);
  1812.  
  1813.         if (!iff.raw)
  1814.         {   addreactionnode(&List2, "Global attributes:");
  1815.  
  1816.             label(" Driver mode:");
  1817.             interpret(10, (ULONG) contents[which].DataPtr[16]);
  1818.  
  1819.             label(" Paper format:");
  1820.             interpret(11, (ULONG) contents[which].DataPtr[17]);
  1821.  
  1822.             // now two reserved bytes
  1823.  
  1824.             label(" Copies:");
  1825.             svalue = getslong(&(contents[which].DataPtr[20]));
  1826.             snumcat(svalue, TRUE);
  1827.  
  1828.             label(" Paper width:");
  1829.             svalue = getslong(&(contents[which].DataPtr[24]));
  1830.             snumcat(svalue, FALSE);
  1831.             strcat(tempstring1, " millipoints");
  1832.             addreactionnode(&List2, tempstring1);
  1833.  
  1834.             label(" Paper height:");
  1835.             svalue = getslong(&(contents[which].DataPtr[28]));
  1836.             snumcat(svalue, FALSE);
  1837.             strcat(tempstring1, " millipoints");
  1838.             addreactionnode(&List2, tempstring1);
  1839.  
  1840.             label(" Horizontal DPI:");
  1841.             svalue = getslong(&(contents[which].DataPtr[32]));
  1842.             snumcat(svalue, FALSE);
  1843.             strcat(tempstring1, " millipoints");
  1844.             addreactionnode(&List2, tempstring1);
  1845.  
  1846.             label(" Vertical DPI:");
  1847.             svalue = getslong(&(contents[which].DataPtr[36]));
  1848.             snumcat(svalue, FALSE);
  1849.             strcat(tempstring1, " millipoints");
  1850.             addreactionnode(&List2, tempstring1);
  1851.  
  1852.             addreactionnode(&List2, "Text options:");
  1853.  
  1854.             label(" Font:");
  1855.             interpret(12, (ULONG) contents[which].DataPtr[40]);
  1856.  
  1857.             label(" Pitch:");
  1858.             interpret(13, (ULONG) contents[which].DataPtr[41]);
  1859.  
  1860.             label(" Orientation:");
  1861.             interpret(14, (ULONG) contents[which].DataPtr[42]);
  1862.  
  1863.             label(" Tab stops:");
  1864.             interpret(15, (ULONG) contents[which].DataPtr[43]);
  1865.  
  1866.             // now eight reserved bytes
  1867.  
  1868.             addreactionnode(&List2, "Text dimensions:");
  1869.  
  1870.             label(" Left margin:");
  1871.             svalue = getslong(&(contents[which].DataPtr[52]));
  1872.             snumcat(svalue, FALSE);
  1873.             strcat(tempstring1, " millipoints");
  1874.             addreactionnode(&List2, tempstring1);
  1875.  
  1876.             label(" Right margin:");
  1877.             svalue = getslong(&(contents[which].DataPtr[56]));
  1878.             snumcat(svalue, FALSE);
  1879.             strcat(tempstring1, " millipoints");
  1880.             addreactionnode(&List2, tempstring1);
  1881.  
  1882.             label(" Top margin:");
  1883.             svalue = getslong(&(contents[which].DataPtr[60]));
  1884.             snumcat(svalue, FALSE);
  1885.             strcat(tempstring1, " millipoints");
  1886.             addreactionnode(&List2, tempstring1);
  1887.  
  1888.             label(" Bottom margin:");
  1889.             svalue = getslong(&(contents[which].DataPtr[64]));
  1890.             snumcat(svalue, FALSE);
  1891.             strcat(tempstring1, " millipoints");
  1892.             addreactionnode(&List2, tempstring1);
  1893.  
  1894.             label(" Font size:");
  1895.             svalue = getslong(&(contents[which].DataPtr[68]));
  1896.             snumcat(svalue, FALSE);
  1897.             strcat(tempstring1, " millipoints");
  1898.             addreactionnode(&List2, tempstring1);
  1899.  
  1900.             label(" Leading:");
  1901.             svalue = getslong(&(contents[which].DataPtr[72]));
  1902.             snumcat(svalue, FALSE);
  1903.             strcat(tempstring1, " millipoints");
  1904.             addreactionnode(&List2, tempstring1);
  1905.  
  1906.             // now eight reserved bytes
  1907.  
  1908.             addreactionnode(&List2, "Graphics options:");
  1909.  
  1910.             label(" Left edge:");
  1911.             svalue = getslong(&(contents[which].DataPtr[80]));
  1912.             snumcat(svalue, FALSE);
  1913.             strcat(tempstring1, " millipoints");
  1914.             addreactionnode(&List2, tempstring1);
  1915.  
  1916.             label(" Top edge:");
  1917.             svalue = getslong(&(contents[which].DataPtr[84]));
  1918.             snumcat(svalue, FALSE);
  1919.             strcat(tempstring1, " millipoints");
  1920.             addreactionnode(&List2, tempstring1);
  1921.  
  1922.             label(" Width:");
  1923.             svalue = getslong(&(contents[which].DataPtr[88]));
  1924.             snumcat(svalue, FALSE);
  1925.             strcat(tempstring1, " millipoints");
  1926.             addreactionnode(&List2, tempstring1);
  1927.  
  1928.             label(" Height:");
  1929.             svalue = getslong(&(contents[which].DataPtr[92]));
  1930.             snumcat(svalue, FALSE);
  1931.             strcat(tempstring1, " millipoints");
  1932.             addreactionnode(&List2, tempstring1);
  1933.  
  1934.             label(" Image:");
  1935.             interpret(16, (ULONG) contents[which].DataPtr[96]);
  1936.  
  1937.             label(" Shading:");
  1938.             interpret(17, (ULONG) contents[which].DataPtr[97]);
  1939.  
  1940.             label(" Dithering:");
  1941.             interpret(18, (ULONG) contents[which].DataPtr[98]);
  1942.  
  1943.             // now nine reserved bytes
  1944.  
  1945.             addreactionnode(&List2, "Graphics scaling:");
  1946.  
  1947.             label(" Aspect:");
  1948.             interpret(19, (ULONG) contents[which].DataPtr[108]);
  1949.  
  1950.             label(" Scaling type:");
  1951.             interpret(20, (ULONG) contents[which].DataPtr[109]);
  1952.  
  1953.             // now one reserved byte
  1954.  
  1955.             label(" Centering:");
  1956.             interpret(21, (ULONG) contents[which].DataPtr[111]);
  1957.         }   }
  1958.         elif (!strcmp(contents[which].name, "PGFX"))
  1959.         {   chunkdesc("Printer graphics preferences", TRUE);
  1960.  
  1961.         if (!iff.raw)
  1962.         {
  1963.             label("Aspect:");
  1964.             uvalue = getuword(&(contents[which].DataPtr[16]));
  1965.             interpret(19, uvalue);
  1966.  
  1967.             label("Shading:");
  1968.             uvalue = getuword(&(contents[which].DataPtr[18]));
  1969.             interpret(22, uvalue);
  1970.  
  1971.             label("Image:");
  1972.             uvalue = getuword(&(contents[which].DataPtr[20]));
  1973.             interpret(16, uvalue);
  1974.  
  1975.             label("Threshold:");
  1976.             svalue = getsword(&(contents[which].DataPtr[22]));
  1977.             snumcat(svalue, TRUE);
  1978.  
  1979.             addreactionnode(&List2, "Colour correction:");
  1980.  
  1981.             label(" Red?");
  1982.             dobool(contents[which].DataPtr[24] & 1); // PCCF_RED
  1983.  
  1984.             label(" Green?");
  1985.             dobool(contents[which].DataPtr[24] & 2); // PCCF_GREEN
  1986.  
  1987.             label(" Blue?");
  1988.             dobool(contents[which].DataPtr[24] & 4); // PCCF_BLUE
  1989.  
  1990.             label("Dimensions:");
  1991.             interpret(23, (ULONG) contents[which].DataPtr[25]);
  1992.  
  1993.             label("Dithering:");
  1994.             interpret(24, (ULONG) contents[which].DataPtr[26]);
  1995.  
  1996.             label("Flags:");
  1997.             addreactionnode(&List2, tempstring1);
  1998.  
  1999.             uvalue = getuword(&(contents[which].DataPtr[27]));
  2000.  
  2001.             label(" Centre image?");
  2002.             dobool((UBYTE) (uvalue & 1)); // PGFF_CENTER_IMAGE
  2003.  
  2004.             label(" Integer scaling?");
  2005.             dobool((UBYTE) (uvalue & 2)); // PGFF_INTEGER_SCALING
  2006.  
  2007.             label(" Antialiasing?");
  2008.             dobool((UBYTE) (uvalue & 4)); // PGFF_ANTI_ALIAS
  2009.  
  2010.             label("Print density:");
  2011.             snumcat((SLONG) contents[which].DataPtr[29], FALSE);
  2012.             if (contents[which].DataPtr[29] < 1 || contents[which].DataPtr[29] > 7)
  2013.             {   strcat(tempstring1, "!");
  2014.             }
  2015.             addreactionnode(&List2, tempstring1);
  2016.  
  2017.             label("Maximum width:");
  2018.             uvalue = getuword(&(contents[which].DataPtr[30]));
  2019.             unumcat(uvalue, TRUE);
  2020.  
  2021.             label("Maximum height:");
  2022.             uvalue = getuword(&(contents[which].DataPtr[32]));
  2023.             unumcat(uvalue, TRUE);
  2024.  
  2025.             label("Offset:");
  2026.             snumcat((SLONG) contents[which].DataPtr[34], FALSE);
  2027.             strcat(tempstring1, ",");
  2028.             snumcat((SLONG) contents[which].DataPtr[35], TRUE);
  2029.         }   }
  2030.         elif (!strcmp(contents[which].name, "PTXT"))
  2031.         {   chunkdesc("Printer text preferences", TRUE);
  2032.  
  2033.         if (!iff.raw)
  2034.         {
  2035.             label("Driver filename:");
  2036.             strcat(tempstring1, &(contents[which].DataPtr[16]));
  2037.             // 32-character field, so it doesn't need truncation
  2038.             addreactionnode(&List2, tempstring1);
  2039.  
  2040.             label("Port:");
  2041.             interpret(25, (ULONG) contents[which].DataPtr[48]);
  2042.  
  2043.             label("Paper type:");
  2044.             uvalue = getuword(&(contents[which].DataPtr[49]));
  2045.             interpret(26, uvalue);
  2046.  
  2047.             label("Paper size:");
  2048.             uvalue = getuword(&(contents[which].DataPtr[51]));
  2049.             interpret(27, uvalue);
  2050.  
  2051.             label("Paper length:");
  2052.             uvalue = getuword(&(contents[which].DataPtr[53]));
  2053.             unumcat(uvalue, FALSE);
  2054.             strcat(tempstring1, " lines");
  2055.             addreactionnode(&List2, tempstring1);
  2056.  
  2057.             label("Pitch:");
  2058.             uvalue = getuword(&(contents[which].DataPtr[55]));
  2059.             interpret(28, uvalue);
  2060.  
  2061.             label("Spacing:");
  2062.             uvalue = getuword(&(contents[which].DataPtr[57]));
  2063.             interpret(29, uvalue);
  2064.  
  2065.             label("Left margin:");
  2066.             uvalue = getuword(&(contents[which].DataPtr[59]));
  2067.             unumcat(uvalue, TRUE);
  2068.  
  2069.             label("Right margin:");
  2070.             uvalue = getuword(&(contents[which].DataPtr[61]));
  2071.             unumcat(uvalue, TRUE);
  2072.  
  2073.             label("Quality:");
  2074.             uvalue = getuword(&(contents[which].DataPtr[63]));
  2075.             interpret(30, uvalue);
  2076.         }   }
  2077.         elif (!strcmp(contents[which].name, "SOND"))
  2078.         {   chunkdesc("Sound preferences", TRUE);
  2079.  
  2080.             // 16 reserved bytes at start
  2081.  
  2082.         if (!iff.raw)
  2083.         {   label("Flash display?");
  2084.             uvalue = getuword(&contents[which].DataPtr[16]); // BOOL
  2085.             dobool((UBYTE) uvalue);
  2086.  
  2087.             label("Make sounds?");
  2088.             uvalue = getuword(&contents[which].DataPtr[18]); // BOOL
  2089.             dobool((UBYTE) uvalue);
  2090.  
  2091.             label("Type of sound:");
  2092.             uvalue = getuword(&contents[which].DataPtr[20]); // UWORD
  2093.             interpret(31, uvalue);
  2094.  
  2095.             label("Volume:");
  2096.             uvalue = getuword(&contents[which].DataPtr[22]); // uword
  2097.             unumcat(uvalue, FALSE);
  2098.             if (uvalue > 64)
  2099.             {   strcat(tempstring1, "!");
  2100.             }
  2101.             strcat(tempstring1, "/64");
  2102.             addreactionnode(&List2, tempstring1);
  2103.  
  2104.             label("Period:");
  2105.             uvalue = getuword(&contents[which].DataPtr[24]); // uword
  2106.             unumcat(uvalue, FALSE);
  2107.             if (uvalue < 127 || uvalue > 2500)
  2108.             {   strcat(tempstring1, "!");
  2109.             }
  2110.             addreactionnode(&List2, tempstring1);
  2111.  
  2112.             label("Beep length:");
  2113.             uvalue = getuword(&contents[which].DataPtr[26]); // uword
  2114.             unumcat(uvalue, TRUE);
  2115.  
  2116.             label("Sample filename:");
  2117.             strcat(tempstring1, &contents[which].DataPtr[28]); // 256 chars
  2118.             addreactionnode(&List2, tempstring1);
  2119.         }   }
  2120.         elif (!strcmp(contents[which].name, "PTRN"))
  2121.         {   chunkdesc("Workbench pattern preferences", TRUE);
  2122.  
  2123.             // 16 reserved bytes at start
  2124.  
  2125.         if (!iff.raw)
  2126.         {
  2127.             label("Which pattern?");
  2128.             uvalue = getuword(&contents[which].DataPtr[16]); // UWORD
  2129.             interpret(32, uvalue);
  2130.  
  2131.             uvalue = getuword(&contents[which].DataPtr[18]); // UWORD
  2132.  
  2133.             label("Data contains pattern?");
  2134.             dobool((UBYTE) (uvalue & 1)); // WBPF_PATTERN
  2135.  
  2136.             label("Remap pattern?"); // note that this one is inverted
  2137.             if (uvalue & 16) // WBPF_NOREMAP
  2138.             {   strcat(tempstring1, "No");
  2139.             } else
  2140.             {   strcat(tempstring1, "Yes");
  2141.             }
  2142.             addreactionnode(&List2, tempstring1);
  2143.  
  2144.             label("Dither quality:");
  2145.             if (uvalue & 768) // these comparisons are order-dependent
  2146.             {   strcat(tempstring1, "Best");
  2147.             } elif (uvalue & 512)
  2148.             {   strcat(tempstring1, "Good");
  2149.             } elif (uvalue & 256)
  2150.             {   strcat(tempstring1, "Poor");
  2151.             } else
  2152.             {   strcat(tempstring1, "Default");
  2153.             }
  2154.             addreactionnode(&List2, tempstring1);
  2155.  
  2156.             label("Colour quality:");
  2157.             if (uvalue & 3072) // these comparisons are order-dependent
  2158.             {   strcat(tempstring1, "Best");
  2159.             } elif (uvalue & 2048)
  2160.             {   strcat(tempstring1, "Good");
  2161.             } elif (uvalue & 1024)
  2162.             {   strcat(tempstring1, "Poor");
  2163.             } else
  2164.             {   strcat(tempstring1, "Default");
  2165.             }
  2166.             addreactionnode(&List2, tempstring1);
  2167.  
  2168.             label("Layout:");
  2169.             if (uvalue & 12288) // these comparisons are order-dependent
  2170.             {   strcat(tempstring1, "Scale well");
  2171.             } elif (uvalue & 8192)
  2172.             {   strcat(tempstring1, "Scale");
  2173.             } elif (uvalue & 4096)
  2174.             {   strcat(tempstring1, "Centre");
  2175.             } else
  2176.             {   strcat(tempstring1, "Tile");
  2177.             }
  2178.             addreactionnode(&List2, tempstring1);
  2179.  
  2180.             label("Revision:"); // BYTE
  2181.             snumcat((SLONG) contents[which].DataPtr[20], TRUE);
  2182.  
  2183.             label("Pattern depth:"); // BYTE
  2184.             snumcat((SLONG) contents[which].DataPtr[21], TRUE);
  2185.  
  2186.             label("Data length:"); // UWORD
  2187.             uvalue = getuword(&contents[which].DataPtr[22]);
  2188.             unumcat(uvalue, TRUE);
  2189.         }   }
  2190.         elif (!strcmp(contents[which].name, "PNTR"))
  2191.         {   chunkdesc("Pointer preferences", TRUE);
  2192.  
  2193.             // 16 reserved bytes at start
  2194.  
  2195.         if (!iff.raw)
  2196.         {   label("Which pointer?");
  2197.             uvalue = getuword(&contents[which].DataPtr[16]); // UWORD
  2198.             interpret(33, uvalue);
  2199.  
  2200.             label("Horizontal size:");
  2201.             uvalue = getuword(&contents[which].DataPtr[18]); // UWORD
  2202.             interpret(34, uvalue);
  2203.  
  2204.             label("Width:");
  2205.             uvalue = getuword(&contents[which].DataPtr[20]); // UWORD
  2206.             unumcat(uvalue, FALSE);
  2207.             strcat(tempstring1, " pixels");
  2208.             addreactionnode(&List2, tempstring1);
  2209.  
  2210.             label("Height:");
  2211.             uvalue = getuword(&contents[which].DataPtr[22]); // UWORD
  2212.             unumcat(uvalue, FALSE);
  2213.             strcat(tempstring1, " pixels");
  2214.             addreactionnode(&List2, tempstring1);
  2215.  
  2216.             label("Depth:");
  2217.             uvalue = getuword(&contents[which].DataPtr[24]); // UWORD
  2218.             unumcat(uvalue, FALSE);
  2219.             strcat(tempstring1, " planes");
  2220.             addreactionnode(&List2, tempstring1);
  2221.  
  2222.             label("Vertical size:");
  2223.             uvalue = getuword(&contents[which].DataPtr[26]); // UWORD
  2224.             interpret(35, uvalue);
  2225.  
  2226.             label("Hotspot coordinates:");
  2227.             uvalue = getuword(&contents[which].DataPtr[28]); // UWORD
  2228.             unumcat(uvalue, FALSE);
  2229.             strcat(tempstring1, ",");
  2230.             uvalue = getuword(&contents[which].DataPtr[30]); // UWORD
  2231.             unumcat(uvalue, TRUE);
  2232.         }   }
  2233.         elif (!strcmp(contents[which].name, "PALT")) // ignored
  2234.         {   chunkdesc("Palette preferences", FALSE);
  2235.         } elif (!strcmp(contents[which].name, "AHIG"))
  2236.         {   chunkdesc("AHI global preferences", TRUE);
  2237.  
  2238.             if (!iff.raw)
  2239.             {   label("Debug level:");
  2240.                 uvalue = getuword(contents[which].DataPtr); // UWORD
  2241.                 interpret(36, uvalue);
  2242.  
  2243.                 label("Disable surround sound?");
  2244.                 uvalue = getuword(&contents[which].DataPtr[2]); // BOOL
  2245.                 dobool((UBYTE) uvalue);
  2246.  
  2247.                 label("Disable echo?");
  2248.                 uvalue = getuword(&contents[which].DataPtr[4]); // BOOL
  2249.                 dobool((UBYTE) uvalue);
  2250.  
  2251.                 label("Fast echo?");
  2252.                 uvalue = getuword(&contents[which].DataPtr[6]); // BOOL
  2253.                 dobool((UBYTE) uvalue);
  2254.  
  2255.                 label("Maximum CPU usage:");
  2256.                 svalue = getslong(&(contents[which].DataPtr[8]));
  2257.                 svalue /= 1024; // LONG (Fixed)
  2258.                 snumcat(svalue, FALSE);
  2259.                 strcat(tempstring1, "/64");
  2260.                 addreactionnode(&List2, tempstring1);
  2261.  
  2262.                 label("Clip master volume?");
  2263.                 uvalue = getuword(&contents[which].DataPtr[12]); // BOOL
  2264.                 dobool((UBYTE) uvalue);
  2265.         }   }
  2266.         elif (!strcmp(contents[which].name, "AHIU"))
  2267.         {   chunkdesc("AHI unit preferences", TRUE);
  2268.  
  2269.             if (!iff.raw)
  2270.             {   label("Unit:");
  2271.                 snumcat((SLONG) contents[which].DataPtr[0], TRUE); // UBYTE
  2272.  
  2273.                 // byte 1 is a pad byte
  2274.  
  2275.                 label("Channels:");
  2276.                 uvalue = getuword(&contents[which].DataPtr[2]); // UWORD
  2277.                 unumcat(uvalue, TRUE);
  2278.  
  2279.                 label("Audio mode:");
  2280.                 uvalue = getuword(&contents[which].DataPtr[4]); // ULONG
  2281.                 unumcat(uvalue, TRUE); // perhaps this can be interpreted?
  2282.  
  2283.                 label("Frequency:");
  2284.                 uvalue = getuword(&contents[which].DataPtr[8]); // ULONG
  2285.                 unumcat(uvalue, TRUE);
  2286.  
  2287.                 label("Monitor volume:");
  2288.                 svalue = getslong(&(contents[which].DataPtr[12]));
  2289.                 svalue /= 1024; // LONG (Fixed)
  2290.                 snumcat(svalue, FALSE);
  2291.                 strcat(tempstring1, "/64");
  2292.                 addreactionnode(&List2, tempstring1);
  2293.  
  2294.                 label("Input gain:");
  2295.                 svalue = getslong(&(contents[which].DataPtr[16]));
  2296.                 svalue /= 1024; // LONG (Fixed)
  2297.                 snumcat(svalue, FALSE);
  2298.                 strcat(tempstring1, "/64");
  2299.                 addreactionnode(&List2, tempstring1);
  2300.  
  2301.                 label("Output volume:");
  2302.                 svalue = getslong(&(contents[which].DataPtr[20]));
  2303.                 svalue /= 1024; // LONG (Fixed)
  2304.                 snumcat(svalue, FALSE);
  2305.                 strcat(tempstring1, "/64");
  2306.                 addreactionnode(&List2, tempstring1);
  2307.  
  2308.                 label("Input:");
  2309.                 uvalue = getuword(&contents[which].DataPtr[24]); // ULONG
  2310.                 unumcat(uvalue, TRUE); // perhaps this can be interpreted?
  2311.  
  2312.                 label("Output:");
  2313.                 uvalue = getuword(&contents[which].DataPtr[28]); // ULONG
  2314.                 unumcat(uvalue, TRUE); // perhaps this can be interpreted?
  2315.         }   }
  2316.         elif (!strcmp(contents[which].name, "WBNC"))
  2317.         {   chunkdesc("Workbench preferences", TRUE);
  2318.  
  2319.         if (!iff.raw)
  2320.         {
  2321.             label("Default stack size:");
  2322.             uvalue = getulong(contents[which].DataPtr); // ULONG
  2323.             unumcat(uvalue, FALSE);
  2324.             strcat(tempstring1, " bytes");
  2325.             addreactionnode(&List2, tempstring1);
  2326.  
  2327.             label("Type restart time:");
  2328.             uvalue = getulong(&contents[which].DataPtr[4]); // ULONG
  2329.             unumcat(uvalue, FALSE);
  2330.             strcat(tempstring1, " seconds");
  2331.             addreactionnode(&List2, tempstring1);
  2332.  
  2333.             label("Icon precision:");
  2334.             uvalue = getulong(&contents[which].DataPtr[8]); // ULONG
  2335.             if (uvalue == (ULONG) -1) // PRECISION_EXACT
  2336.             {   strcat(tempstring1, "-1 (exact)");
  2337.             } elif (uvalue == 0) // PRECISION_IMAGE
  2338.             {   strcat(tempstring1, "0 (image)");
  2339.             } elif (uvalue == 16) // PRECISION_ICON
  2340.             {   strcat(tempstring1, "16 (icon)");
  2341.             } elif (uvalue == 32) // PRECISION_GUI
  2342.             {   strcat(tempstring1, "32 (GUI)");
  2343.             } else
  2344.             {   strcat(tempstring1, "?");
  2345.             }
  2346.             addreactionnode(&List2, tempstring1);
  2347.  
  2348.             addreactionnode(&List2, "Emboss rectangle:");
  2349.  
  2350.             label(" Top-left corner:");
  2351.             svalue = getsword(&contents[which].DataPtr[12]); // WORD
  2352.             snumcat(svalue, FALSE);
  2353.             strcat(tempstring1, ",");
  2354.             svalue = getuword(&contents[which].DataPtr[14]); // WORD
  2355.             snumcat(svalue, TRUE);
  2356.  
  2357.             label(" Bottom-right corner:");
  2358.             svalue = getsword(&contents[which].DataPtr[16]); // WORD
  2359.             snumcat(svalue, FALSE);
  2360.             strcat(tempstring1, ",");
  2361.             svalue = getuword(&contents[which].DataPtr[18]); // WORD
  2362.             snumcat(svalue, TRUE);
  2363.  
  2364.             label("Borderless?");
  2365.             uvalue = getuword(&contents[which].DataPtr[20]); // BOOL
  2366.             dobool((UBYTE) uvalue);
  2367.  
  2368.             label("Max. filename length:");
  2369.             svalue = getslong(&contents[which].DataPtr[22]); // LONG
  2370.             snumcat(svalue, FALSE);
  2371.             strcat(tempstring1, " characters");
  2372.             addreactionnode(&List2, tempstring1);
  2373.  
  2374.             label("NewIcons support?");
  2375.             uvalue = getuword(&contents[which].DataPtr[26]); // BOOL
  2376.             dobool((UBYTE) uvalue);
  2377.  
  2378.             label("ColourIcons support?");
  2379.             uvalue = getuword(&contents[which].DataPtr[28]); // BOOL
  2380.             dobool((UBYTE) uvalue);
  2381.  
  2382.             // remainder of these are new for OS3.9
  2383.  
  2384.             if (contents[which].bytes > 30)
  2385.             {   label("Image memory type:");
  2386.                 uvalue = getulong(&contents[which].DataPtr[30]); // ULONG
  2387.                 if (uvalue == 1)
  2388.                 {   strcat(tempstring1, "1 (Other memory)");
  2389.                 } elif (uvalue == 2)
  2390.                 {   strcat(tempstring1, "2 (Graphics (chip) memory)");
  2391.                 } else
  2392.                 {   strcat(tempstring1, "?");
  2393.                 }
  2394.                 addreactionnode(&List2, tempstring1);
  2395.  
  2396.                 label("Lock pens?");
  2397.                 uvalue = getuword(&contents[which].DataPtr[34]); // BOOL
  2398.                 dobool((UBYTE) uvalue);
  2399.  
  2400.                 label("Title bar?"); // this one is inverted
  2401.                 uvalue = getuword(&contents[which].DataPtr[36]); // BOOL
  2402.                 if (uvalue)
  2403.                 {   strcat(tempstring1, "No");
  2404.                 } else
  2405.                 {   strcat(tempstring1, "Yes");
  2406.                 }
  2407.                 addreactionnode(&List2, tempstring1);
  2408.  
  2409.                 label("Volume gauge?"); // this one is inverted
  2410.                 uvalue = getuword(&contents[which].DataPtr[38]); // BOOL
  2411.                 if (uvalue)
  2412.                 {   strcat(tempstring1, "No");
  2413.                 } else
  2414.                 {   strcat(tempstring1, "Yes");
  2415.                 }
  2416.                 addreactionnode(&List2, tempstring1);
  2417.         }   }   }
  2418.         elif (!strcmp(contents[which].name, "WBHD"))
  2419.         {   chunkdesc("Workbench hidden device preferences", TRUE);
  2420.  
  2421.             if (!iff.raw)
  2422.             {   label("Name:");
  2423.                 strcat(tempstring1, contents[which].DataPtr);
  2424.                 addreactionnode(&List2, tempstring1);
  2425.         }   }
  2426.         elif (!strcmp(contents[which].name, "LCLE"))
  2427.         {   chunkdesc("Locale preferences", TRUE);
  2428.  
  2429.             // 16 reserved bytes at start
  2430.  
  2431.         if (!iff.raw)
  2432.         {   label("Country name:");
  2433.             strcat(tempstring1, &contents[which].DataPtr[16]); // 32 chars
  2434.             addreactionnode(&List2, tempstring1);
  2435.  
  2436.             label("Preferred languages:");
  2437.             addreactionnode(&List2, tempstring1);
  2438.  
  2439.             for (i = 1; i <= 10; i++)
  2440.             {   strcpy(tempstring3, " ");
  2441.                 if (i < 10)
  2442.                 {   strcat(tempstring3, " ");
  2443.                 }
  2444.                 stcl_d(tempstring2, i);
  2445.                 strcat(tempstring3, tempstring2);
  2446.                 strcat(tempstring3, ":");
  2447.                 label(tempstring3);
  2448.                 strcat(tempstring1, &contents[which].DataPtr[48 + ((i - 1) * 30)]); // 10 entries of 30 chars each
  2449.                 addreactionnode(&List2, tempstring1);
  2450.             }
  2451.  
  2452.             label("Time from GMT:");
  2453.             svalue = getslong(&contents[which].DataPtr[348]); // LONG
  2454.             snumcat(svalue, FALSE);
  2455.             strcat(tempstring1, " minutes");
  2456.             addreactionnode(&List2, tempstring1);
  2457.  
  2458.             label("Flags:");
  2459.             uvalue = getulong(&contents[which].DataPtr[352]); // ULONG
  2460.             unumcat(uvalue, TRUE);
  2461.  
  2462.             docountry(&contents[which].DataPtr[356]);
  2463.         }   }
  2464.         elif (!strcmp(contents[which].name, "CTRY"))
  2465.         {   chunkdesc("Country preferences", TRUE);
  2466.  
  2467.             if (!iff.raw)
  2468.             {   docountry(contents[which].DataPtr);
  2469.         }   }
  2470.         elif (!strcmp(contents[which].name, "RACT"))
  2471.         {   chunkdesc("ReAction preferences", TRUE);
  2472.  
  2473.         if (!iff.raw)
  2474.         {
  2475.             label("Bevel type:"); // UWORD
  2476.             uvalue = getuword(contents[which].DataPtr);
  2477.             interpret(37, uvalue);
  2478.  
  2479.             label("Glyph type:"); // UWORD
  2480.             uvalue = getuword(&contents[which].DataPtr[2]);
  2481.             interpret(38, uvalue);
  2482.  
  2483.             label("Layout spacing:"); // UWORD
  2484.             uvalue = getuword(&contents[which].DataPtr[4]);
  2485.             unumcat(uvalue, TRUE);
  2486.  
  2487.             label("3D Proportional?");
  2488.             uvalue = getuword(&contents[which].DataPtr[6]); // BOOL
  2489.             dobool((UBYTE) uvalue);
  2490.  
  2491.             label("Label pen:"); // UWORD
  2492.             uvalue = getuword(&contents[which].DataPtr[8]);
  2493.             unumcat(uvalue, TRUE);
  2494.  
  2495.             label("Label placement:"); // UWORD
  2496.             uvalue = getuword(&contents[which].DataPtr[10]);
  2497.             /* This has been reverse-engineered
  2498.             using the ReAction preferences editor */
  2499.             interpret(39, uvalue);
  2500.  
  2501.             label("3D Label?");
  2502.             uvalue = getuword(&contents[which].DataPtr[12]); // BOOL
  2503.             dobool((UBYTE) uvalue);
  2504.  
  2505.             label("Refreshing Method:");
  2506.             uvalue = getuword(&contents[which].DataPtr[14]); // BOOL
  2507.             if (uvalue)
  2508.             {   strcat(tempstring1, "Simple");
  2509.             } else
  2510.             {   strcat(tempstring1, "Smart");
  2511.             }
  2512.             addreactionnode(&List2, tempstring1);
  2513.  
  2514.             label("3D Look?");
  2515.             uvalue = getuword(&contents[which].DataPtr[16]); // BOOL
  2516.             dobool((UBYTE) uvalue);
  2517.  
  2518.             addreactionnode(&List2, "Fallback font:");
  2519.             dotextattr(&contents[which].DataPtr[18]); // struct TextAttr (8 bytes)
  2520.             addreactionnode(&List2, "Label font:");
  2521.             dotextattr(&contents[which].DataPtr[26]); // struct TextAttr (8 bytes)
  2522.  
  2523.             label("Fallback font name:");
  2524.             strcat(tempstring1, &contents[which].DataPtr[34]); // 128 UBYTEs
  2525.             addreactionnode(&List2, tempstring1);
  2526.  
  2527.             label("Label font name:");
  2528.             strcat(tempstring1, &contents[which].DataPtr[162]); // 128 UBYTEs
  2529.             addreactionnode(&List2, tempstring1);
  2530.  
  2531.             label("Backdrop pattern:");
  2532.             strcat(tempstring1, &contents[which].DataPtr[290]); // 256 UBYTEs
  2533.             addreactionnode(&List2, tempstring1);
  2534.         }   }
  2535.         elif (!strcmp(contents[which].name, "PRHD"))
  2536.         {   chunkdesc("Preferences header", TRUE);
  2537.  
  2538.         if (!iff.raw)
  2539.         {   label("Version:");
  2540.             snumcat((SLONG) contents[which].DataPtr[0], TRUE);
  2541.                                
  2542.             label("Type:");
  2543.             snumcat((SLONG) contents[which].DataPtr[1], TRUE);
  2544.  
  2545.             label("Flags:");
  2546.             uvalue = getuword(&(contents[which].DataPtr[2]));
  2547.             unumcat(uvalue, TRUE);
  2548.     }   }   }
  2549.     elif (!strcmp(queryform, "SMUS"))
  2550.     {   if (!strcmp(contents[which].name, "SHDR"))
  2551.         {   chunkdesc("Global information for the score", TRUE);
  2552.  
  2553.         if (!iff.raw)
  2554.         {
  2555.             label("Tempo:");
  2556.             uvalue = getuword(contents[which].DataPtr);
  2557.             uvalue /= 128;
  2558.             unumcat(uvalue, FALSE);
  2559.             strcat(tempstring1, " bpm");
  2560.             addreactionnode(&List2, tempstring1);
  2561.  
  2562.             label("Volume:");
  2563.             snumcat((SLONG) contents[which].DataPtr[2], FALSE);
  2564.             strcat(tempstring1, "/127");
  2565.             addreactionnode(&List2, tempstring1);
  2566.  
  2567.             label("Tracks:");
  2568.             snumcat((SLONG) contents[which].DataPtr[3], TRUE);
  2569.         }   }
  2570.         elif (!strcmp(contents[which].name, "INS1"))
  2571.         {   chunkdesc("Identifies an instrument to use", TRUE);
  2572.  
  2573.         if (!iff.raw)
  2574.         {
  2575.             label("Register number:");
  2576.             snumcat((SLONG) contents[which].DataPtr[0], TRUE); // UBYTE
  2577.  
  2578.             label("Reference type:");
  2579.             interpret(40, (ULONG) contents[which].DataPtr[1]); // UBYTE
  2580.  
  2581.             label("MIDI channel:");
  2582.             if (contents[which].DataPtr[1] == 1) // if find on MIDI
  2583.             {   snumcat((SLONG) contents[which].DataPtr[2], TRUE); // UBYTE
  2584.             } else
  2585.             {   strcat(tempstring1, "n/a");
  2586.                 addreactionnode(&List2, tempstring1);
  2587.             }
  2588.  
  2589.             label("MIDI preset:");
  2590.             if (contents[which].DataPtr[1] == 1) // if find on MIDI
  2591.             {   snumcat((SLONG) contents[which].DataPtr[3], TRUE);
  2592.             } else
  2593.             {   strcat(tempstring1, "n/a");
  2594.                 addreactionnode(&List2, tempstring1);
  2595.             }
  2596.  
  2597.             label("Instrument name:");
  2598.             strcat(tempstring1, (STRPTR) contents[which].DataPtr + 4); // STRPTR
  2599.             addreactionnode(&List2, tempstring1);
  2600.         }   }
  2601.         elif (!strcmp(contents[which].name, "TRAK"))
  2602.         {   chunkdesc("Linear stream of events", FALSE);
  2603.         } elif (!strcmp(contents[which].name, "INST"))
  2604.         {   chunkdesc("Obsolete; use INS1 instead", FALSE);
  2605.         } elif (!stricmp(contents[which].name, "IRev")) // this could also perhaps be IREV
  2606.         {   chunkdesc("Instant Music private chunk", FALSE);
  2607.         } elif (!strcmp(contents[which].name, "BIAS"))
  2608.         {   chunkdesc("Instant Music private chunk", FALSE);
  2609.     }   }
  2610.     elif (!strcmp(queryform, "HEAD"))
  2611.     {   if (!strcmp(contents[which].name, "NEST"))
  2612.         {   chunkdesc("Nesting level", TRUE);
  2613.  
  2614.             if (!iff.raw)
  2615.             {   label("Nesting level:");
  2616.                 uvalue = getuword(contents[which].DataPtr);
  2617.                 unumcat(uvalue, TRUE);
  2618.         }   }
  2619.         elif (!strcmp(contents[which].name, "TEXT"))
  2620.         {   chunkdesc("Heading text", FALSE);
  2621.     }   }
  2622.     elif (!strcmp(queryform, "WORD"))
  2623.     {   if (!strcmp(contents[which].name, "FONT"))
  2624.         {   chunkdesc("Font name/number table", TRUE);
  2625.  
  2626.             if (!iff.raw)
  2627.             {   label("Number:");
  2628.                 snumcat((SLONG) contents[which].DataPtr[0], TRUE); // UBYTE
  2629.  
  2630.                 label("Size:");
  2631.                 uvalue = getuword(&contents[which].DataPtr[1]);
  2632.                 unumcat(uvalue, TRUE);
  2633.  
  2634.                 label("Name:");
  2635.                 strcat(tempstring1, &contents[which].DataPtr[3]);
  2636.                 addreactionnode(&List2, tempstring1);
  2637.         }   }
  2638.         elif (!strcmp(contents[which].name, "COLR"))
  2639.         {   chunkdesc("Colour translation table", TRUE);
  2640.  
  2641.             if (!iff.raw)
  2642.             {   for (i = 0; i <= 7; i++)
  2643.                 {   strcpy(tempstring3, "Colour ");
  2644.                     stcl_d(tempstring2, i);
  2645.                     strcat(tempstring3, tempstring2);
  2646.                     strcat(tempstring3, ":");
  2647.                     label(tempstring3);
  2648.                     snumcat((SLONG) contents[which].DataPtr[i], TRUE);
  2649.         }   }   }
  2650.         elif (!strcmp(contents[which].name, "DOC "))
  2651.         {   chunkdesc("Begin document section", TRUE);
  2652.  
  2653.             if (!iff.raw)
  2654.             {   label("Starting page:");
  2655.                 uvalue = getuword(contents[which].DataPtr);
  2656.                 unumcat(uvalue, TRUE);
  2657.  
  2658.                 label("Numbering style:");
  2659.                 interpret(41, (ULONG) contents[which].DataPtr[2]);
  2660.         }   }
  2661.         elif (!strcmp(contents[which].name, "HEAD"))
  2662.         {   chunkdesc("Begin header section", TRUE);
  2663.  
  2664.             if (!iff.raw)
  2665.             {   label("Page type:");
  2666.                 interpret(42, (ULONG) contents[which].DataPtr[0]);
  2667.  
  2668.                 label("First page?");
  2669.                 dobool(contents[which].DataPtr[1]);
  2670.         }   }
  2671.         elif (!strcmp(contents[which].name, "FOOT"))
  2672.         {   chunkdesc("Begin footer section", TRUE);
  2673.  
  2674.             if (!iff.raw)
  2675.             {   label("Page type:");
  2676.                 interpret(42, (ULONG) contents[which].DataPtr[0]);
  2677.  
  2678.                 label("First page?");
  2679.                 dobool(contents[which].DataPtr[1]);
  2680.         }   }
  2681.         elif (!strcmp(contents[which].name, "PCTS"))
  2682.         {   chunkdesc("Begin picture section", TRUE);
  2683.  
  2684.             if (!iff.raw)
  2685.             {   label("Bitplanes:");
  2686.                 snumcat((SLONG) contents[which].DataPtr[0], TRUE); // UBYTE
  2687.         }   }
  2688.         elif (!strcmp(contents[which].name, "PARA"))
  2689.         {   chunkdesc("New paragraph format", TRUE);
  2690.  
  2691.         if (!iff.raw)
  2692.         {   label("Left indent:");
  2693.             uvalue = getuword(contents[which].DataPtr); // UWORD
  2694.             unumcat(uvalue, FALSE);
  2695.             strcat(tempstring1, " decipoints");
  2696.             addreactionnode(&List2, tempstring1);
  2697.  
  2698.             label("Left margin:");
  2699.             uvalue = getuword(&(contents[which].DataPtr[2])); // UWORD
  2700.             unumcat(uvalue, FALSE);
  2701.             strcat(tempstring1, " decipoints");
  2702.             addreactionnode(&List2, tempstring1);
  2703.  
  2704.             label("Right margin:");
  2705.             uvalue = getuword(&(contents[which].DataPtr[4])); // UWORD
  2706.             unumcat(uvalue, FALSE);
  2707.             strcat(tempstring1, " decipoints");
  2708.             addreactionnode(&List2, tempstring1);
  2709.  
  2710.             label("Line spacing:");
  2711.             if (contents[which].DataPtr[6] == 0)
  2712.             {   strcat(tempstring1, "Single");
  2713.             } elif (contents[which].DataPtr[6] == 16)
  2714.             {   strcat(tempstring1, "Double");
  2715.             } else
  2716.             {   strcat(tempstring1, "?");
  2717.             }
  2718.             addreactionnode(&List2, tempstring1);
  2719.  
  2720.             label("Justification:");
  2721.             interpret(43, (ULONG) contents[which].DataPtr[7]);
  2722.  
  2723.             label("Font number:");
  2724.             uvalue = contents[which].DataPtr[8]; // UBYTE
  2725.             unumcat(uvalue, TRUE);
  2726.  
  2727.             addreactionnode(&List2, " Style:");
  2728.  
  2729.             label(" Underlined?");
  2730.             dobool(contents[which].DataPtr[9] & 1);
  2731.  
  2732.             label(" Bold?");
  2733.             dobool(contents[which].DataPtr[9] & 2);
  2734.  
  2735.             label(" Italic?");
  2736.             dobool(contents[which].DataPtr[9] & 4);
  2737.  
  2738.             label(" Extended?");
  2739.             dobool(contents[which].DataPtr[9] & 8);
  2740.  
  2741.             label(" ColourFont?");
  2742.             dobool(contents[which].DataPtr[9] & 64);
  2743.  
  2744.             label(" Tagged?");
  2745.             dobool(contents[which].DataPtr[9] & 128);
  2746.  
  2747.             label("Miscellaneous style:");
  2748.             interpret(1, (ULONG) contents[which].DataPtr[10]);
  2749.  
  2750.             label("Colour:");
  2751.             uvalue = contents[which].DataPtr[11]; // UBYTE
  2752.             unumcat(uvalue, TRUE);
  2753.         }   }
  2754.         elif (!strcmp(contents[which].name, "TABS"))
  2755.         {   chunkdesc("New tab stop types/locations", TRUE);
  2756.  
  2757.             if (!iff.raw)
  2758.             {   label("Position:");
  2759.                 uvalue = getuword(contents[which].DataPtr); // UWORD
  2760.                 unumcat(uvalue, FALSE);
  2761.                 strcat(tempstring1, " decipoints");
  2762.                 addreactionnode(&List2, tempstring1);
  2763.  
  2764.                 label("Type:");
  2765.                 interpret(44, (ULONG) contents[which].DataPtr[2]);
  2766.         }   }
  2767.         elif (!strcmp(contents[which].name, "PAGE"))
  2768.         {   chunkdesc("Page break", FALSE);
  2769.         } elif (!strcmp(contents[which].name, "TEXT"))
  2770.         {   chunkdesc("Paragraph text", FALSE);
  2771.         } elif (!strcmp(contents[which].name, "PINF"))
  2772.         {   chunkdesc("Picture info", TRUE);
  2773.  
  2774.         if (!iff.raw)
  2775.         {   label("Width:");
  2776.             uvalue = getuword(contents[which].DataPtr); // UWORD
  2777.             unumcat(uvalue, TRUE);
  2778.  
  2779.             label("Height:");
  2780.             uvalue = getuword(&(contents[which].DataPtr[2])); // UWORD
  2781.             unumcat(uvalue, TRUE);
  2782.  
  2783.             label("Page:");
  2784.             uvalue = getuword(&(contents[which].DataPtr[4])); // UWORD
  2785.             unumcat(uvalue, TRUE);
  2786.  
  2787.             label("X-position:");
  2788.             uvalue = getuword(&(contents[which].DataPtr[6])); // UWORD
  2789.             unumcat(uvalue, FALSE);
  2790.             strcat(tempstring1, " decipoints");
  2791.             addreactionnode(&List2, tempstring1);
  2792.  
  2793.             label("Y-position:");
  2794.             uvalue = getuword(&(contents[which].DataPtr[8])); // UWORD
  2795.             unumcat(uvalue, FALSE);
  2796.             strcat(tempstring1, " decipoints");
  2797.             addreactionnode(&List2, tempstring1);
  2798.  
  2799.             label("Masking:");
  2800.             interpret(45, (ULONG) contents[which].DataPtr[10]);
  2801.  
  2802.             label("Compression:");
  2803.             interpret(46, (ULONG) contents[which].DataPtr[11]);
  2804.  
  2805.             label("Transparent colour:");
  2806.             if (contents[which].DataPtr[10] != 2
  2807.              && contents[which].DataPtr[10] != 3)
  2808.             {   strcat(tempstring1, "n/a");
  2809.                 addreactionnode(&List2, tempstring1);
  2810.             } else
  2811.             {   uvalue = getuword(&(contents[which].DataPtr[12])); // UWORD
  2812.                 unumcat(uvalue, TRUE);
  2813.             }
  2814.     }   }   }
  2815.     elif (!strcmp(queryform, "AIFF"))
  2816.     {   if (!strcmp(contents[which].name, "MIDI"))
  2817.         {   chunkdesc("Stores MIDI data", FALSE);
  2818.         } elif (!strcmp(contents[which].name, "MARK"))
  2819.         {   chunkdesc("Points to positions in the sound data", TRUE);
  2820.  
  2821.         if (!iff.raw)
  2822.         {   label("Markers:");
  2823.  
  2824.             svalue = getsword(contents[which].DataPtr);
  2825.             snumcat(svalue, FALSE);
  2826.             if (svalue < 0)
  2827.             {   strcat(tempstring1, "!");
  2828.             }
  2829.             addreactionnode(&List2, tempstring1);
  2830.             markers = svalue;
  2831.             if (markers > 0)
  2832.             {   currentpos = 2;
  2833.                 for (i = 1; i <= markers; i++)
  2834.                 {   strcpy(tempstring3, "Marker ");
  2835.                     stcl_d(tempstring2, i);
  2836.                     strcat(tempstring3, tempstring2);
  2837.                     strcat(tempstring3, ":");
  2838.                     label(tempstring3);
  2839.                     addreactionnode(&List2, tempstring1);
  2840.  
  2841.                     label(" ID:");
  2842.                     svalue = getsword(&(contents[which].name[currentpos]));
  2843.                     snumcat(svalue, FALSE);
  2844.                     if (svalue < 1)
  2845.                     {   strcat(tempstring1, "!");
  2846.                     }
  2847.                     addreactionnode(&List2, tempstring1);
  2848.                     currentpos += 2;
  2849.  
  2850.                     label(" Position:");
  2851.                     uvalue = getulong(&(contents[which].name[currentpos]));
  2852.                     unumcat(uvalue, TRUE);
  2853.                     currentpos += 4;
  2854.  
  2855.                     label(" Name:");
  2856.                     uvalue = contents[which].name[currentpos++];
  2857.                     // the number of characters in the string
  2858.                     if (uvalue < MEDFIELD)
  2859.                     {   strncat(tempstring1, &(contents[which].name[currentpos]), uvalue);
  2860.                     } else
  2861.                     {   strncat(tempstring1, &(contents[which].name[currentpos]), MEDFIELD);
  2862.                     }
  2863.                     addreactionnode(&List2, tempstring1);
  2864.                     currentpos += uvalue;
  2865.                     if (uvalue % 2)
  2866.                     {   currentpos++; // skip pad byte, if appropriate
  2867.         }   }   }   }   }
  2868.         elif (!strcmp(contents[which].name, "AESD"))
  2869.         {   chunkdesc("Pertinent to autio recording devices", FALSE);
  2870.         } elif (!strcmp(contents[which].name, "COMT"))
  2871.         {   chunkdesc("Stores comments", TRUE);
  2872.  
  2873.         if (!iff.raw)
  2874.         {   label("Comments:");
  2875.             svalue = getsword(contents[which].DataPtr);
  2876.             snumcat(svalue, FALSE);
  2877.             if (svalue < 0)
  2878.             {   strcat(tempstring1, "!");
  2879.             }
  2880.             addreactionnode(&List2, tempstring1);
  2881.  
  2882.             // we could have a 'comments' variable, but we just reuse
  2883.             // the 'markers' variable.
  2884.             markers = svalue;
  2885.             if (markers > 0)
  2886.             {   currentpos = 2;
  2887.                 for (i = 1; i <= markers; i++)
  2888.                 {   strcpy(tempstring3, "Comment ");
  2889.                     stcl_d(tempstring2, i);
  2890.                     strcat(tempstring3, tempstring2);
  2891.                     strcat(tempstring3, ":");
  2892.                     label(tempstring3);
  2893.                     addreactionnode(&List2, tempstring1);
  2894.  
  2895.                     label(" Created on:");
  2896.                     uvalue = getulong(&(contents[which].DataPtr[currentpos]));
  2897.                     DateTime.dat_Stamp.ds_Days   =   uvalue / 86400;             // days since 1/1/78
  2898.                     DateTime.dat_Stamp.ds_Minute =  (uvalue % 86400) / 60;       // minutes in day
  2899.                     DateTime.dat_Stamp.ds_Tick   = ((uvalue % 86400) % 60) * 50; // ticks in minute
  2900.                     DateTime.dat_Format          = FORMAT_DOS;
  2901.                     DateTime.dat_Flags           = DTF_SUBST;
  2902.                     DateTime.dat_StrDay          = weekdaystring;
  2903.                     DateTime.dat_StrDate         = datestring;
  2904.                     DateTime.dat_StrTime         = timestring;
  2905.                     if (!DateToStr(&DateTime))
  2906.                     {   rq("DateToStr() failed!");
  2907.                     }
  2908.                     strcat(tempstring1, timestring);
  2909.                     strcat(tempstring1, " ");
  2910.                     strcat(tempstring1, weekdaystring);
  2911.                     strcat(tempstring1, " ");
  2912.                     strcat(tempstring1, datestring);
  2913.                     addreactionnode(&List2, tempstring1);
  2914.                     currentpos += 4;
  2915.  
  2916.                     label(" Marker ID:");
  2917.                     svalue = getsword(&(contents[which].DataPtr[currentpos]));
  2918.                     snumcat(svalue, FALSE);
  2919.                     if (svalue < 1)
  2920.                     {    strcat(tempstring1, "!");
  2921.                     }
  2922.                     addreactionnode(&List2, tempstring1);
  2923.                     currentpos += 2;
  2924.  
  2925.                     label(" Comment:");
  2926.                     uvalue = getuword(&(contents[which].DataPtr[currentpos]));
  2927.                     // the number of characters in the string
  2928.                     currentpos += 2;
  2929.                     if (uvalue < MEDFIELD)
  2930.                     {   strncat(tempstring1, &(contents[which].name[currentpos]), uvalue);
  2931.                     } else
  2932.                     {   strncat(tempstring1, &(contents[which].name[currentpos]), MEDFIELD);
  2933.                     }
  2934.                     addreactionnode(&List2, tempstring1);
  2935.                     currentpos += uvalue;
  2936.                     if (uvalue % 2)
  2937.                     {   currentpos++; // skip pad byte, if appropriate
  2938.         }   }   }   }   }
  2939.         elif (!strcmp(contents[which].name, "COMM"))
  2940.         {   chunkdesc("Fundamental parameters for the sampled sound", TRUE);
  2941.  
  2942.         if (!iff.raw)
  2943.         {   label("Channels:");
  2944.             svalue = getsword(contents[which].DataPtr);
  2945.             snumcat(svalue, FALSE);
  2946.             if (svalue == 1)
  2947.             {   strcat(tempstring1, " (mono)");
  2948.             } elif (svalue == 2)
  2949.             {   strcat(tempstring1, " (stereo)");
  2950.             } elif (svalue > 2)
  2951.             {   strcat(tempstring1, " (surround)");
  2952.             }
  2953.             addreactionnode(&List2, tempstring1);
  2954.  
  2955.             label("Sample frames:");
  2956.             uvalue = getulong(&(contents[which].DataPtr[2]));
  2957.             unumcat(uvalue, TRUE);
  2958.  
  2959.             label("Sample quality:");
  2960.             svalue = getsword(&(contents[which].DataPtr[6]));
  2961.             snumcat(svalue, FALSE);
  2962.             strcat(tempstring1, "-bit");
  2963.             addreactionnode(&List2, tempstring1);
  2964.  
  2965.             /* Now there is an 80-bit (10-byte) IEEE 754 Apple-style
  2966.             (SANE) floating point number (not yet implemented):
  2967.                  79 Sign
  2968.               64:78 Exponent
  2969.                0:63 Mantissa */
  2970.  
  2971.             label("Playback rate:");
  2972.             strcat(tempstring1, "-");
  2973.             addreactionnode(&List2, tempstring1);
  2974.         }   }
  2975.         elif (!strcmp(contents[which].name, "APPL"))
  2976.         {   chunkdesc("Application-specific data", TRUE);
  2977.  
  2978.             if (!iff.raw)
  2979.             {   label("Application:");
  2980.                 strcat(tempstring1, contents[which].DataPtr);
  2981.                 if (!strcmp(tempstring1, "pdos"))
  2982.                 {   strcat(tempstring1, " (Apple II)");
  2983.                 }
  2984.                 addreactionnode(&List2, tempstring1);
  2985.         }   }
  2986.         elif (!strcmp(contents[which].name, "SSND"))
  2987.         {   chunkdesc("The actual sample frames", TRUE);
  2988.  
  2989.             if (!iff.raw)
  2990.             {   label("Offset:");
  2991.                 uvalue = getulong(contents[which].DataPtr);
  2992.                 unumcat(uvalue, TRUE);
  2993.  
  2994.                 label("Block size:");
  2995.                 uvalue = getulong(&(contents[which].DataPtr[4]));
  2996.                 unumcat(uvalue, TRUE);
  2997.         }   }
  2998.         elif (!strcmp(contents[which].name, "INST"))
  2999.         {   chunkdesc("Instrument chunk", TRUE);
  3000.  
  3001.         if (!iff.raw)
  3002.         {   label("Base note:");
  3003.             svalue = getsbyte(&(contents[which].DataPtr[0]));
  3004.             snumcat(svalue, FALSE);
  3005.             if (svalue < 0 || svalue > 127)
  3006.                 strcat(tempstring1, "!");
  3007.             addreactionnode(&List2, tempstring1);
  3008.  
  3009.             label("Detune:");
  3010.             svalue = getsbyte(&(contents[which].DataPtr[1]));
  3011.             snumcat(svalue, FALSE);
  3012.             if (svalue < -50 || svalue > 50)
  3013.                 strcat(tempstring1, "!");
  3014.             addreactionnode(&List2, tempstring1);
  3015.  
  3016.             label("Low note:");
  3017.             svalue = getsbyte(&(contents[which].DataPtr[2]));
  3018.             snumcat(svalue, FALSE);
  3019.             if (svalue < 0 || svalue > 127) // actually these couldn't be >127
  3020.                 strcat(tempstring1, "!");
  3021.             addreactionnode(&List2, tempstring1);
  3022.  
  3023.             label("High note:");
  3024.             svalue = getsbyte(&(contents[which].DataPtr[3]));
  3025.             snumcat(svalue, FALSE);
  3026.             if (svalue < 0 || svalue > 127)
  3027.                 strcat(tempstring1, "!");
  3028.             addreactionnode(&List2, tempstring1);
  3029.  
  3030.             label("Low velocity:");
  3031.             svalue = getsbyte(&(contents[which].DataPtr[4]));
  3032.             snumcat(svalue, FALSE);
  3033.             if (svalue < 1 || svalue > 127)
  3034.                 strcat(tempstring1, "!");
  3035.             addreactionnode(&List2, tempstring1);
  3036.  
  3037.             label("High velocity:");
  3038.             svalue = getsbyte(&(contents[which].DataPtr[5]));
  3039.             snumcat(svalue, FALSE);
  3040.             if (svalue < 1 || svalue > 127)
  3041.                 strcat(tempstring1, "!");
  3042.             addreactionnode(&List2, tempstring1);
  3043.  
  3044.             label("Gain:");
  3045.             svalue = getsword(&(contents[which].DataPtr[6]));
  3046.             snumcat(svalue, TRUE);
  3047.  
  3048.             label("Sustain loop:");
  3049.             svalue = getsword(&(contents[which].DataPtr[8]));
  3050.             interpret(47, (ULONG) svalue);
  3051.  
  3052.             label(" Begin loop:");
  3053.             svalue = getsword(&(contents[which].DataPtr[10]));
  3054.             snumcat(svalue, TRUE);
  3055.  
  3056.             label(" End loop:");
  3057.             svalue = getsword(&(contents[which].DataPtr[12]));
  3058.             snumcat(svalue, TRUE);
  3059.  
  3060.             label("Release loop:");
  3061.             svalue = getsword(&(contents[which].DataPtr[14]));
  3062.             interpret(47, (ULONG) svalue);
  3063.  
  3064.             label(" Begin loop:");
  3065.             svalue = getsword(&(contents[which].DataPtr[16]));
  3066.             snumcat(svalue, TRUE);
  3067.  
  3068.             label(" End loop:");
  3069.             svalue = getsword(&(contents[which].DataPtr[18]));
  3070.             snumcat(svalue, TRUE);
  3071.     }   }   }
  3072.     elif (!strcmp(queryform, "CTLG"))
  3073.     {   if (!strcmp(contents[which].name, "LANG"))
  3074.         {   chunkdesc("Language", TRUE);
  3075.  
  3076.             if (!iff.raw)
  3077.             {   label("Language:");
  3078.                 strcat(tempstring1, contents[which].DataPtr);
  3079.                 addreactionnode(&List2, tempstring1);
  3080.         }   }
  3081.         // CSET chunk (32 bytes), STRS chunk?
  3082.     } elif (!strcmp(queryform, "8SVX"))
  3083.     {   if (!strcmp(contents[which].name, "ATAK"))
  3084.         {   chunkdesc("Gives attack amplitude contour (envelope)", FALSE);
  3085.         } elif (!strcmp(contents[which].name, "RLSE"))
  3086.         {   chunkdesc("Gives release amplitude contour (envelope)", FALSE);
  3087.         } elif (!strcmp(contents[which].name, "BODY"))
  3088.         {   chunkdesc("Sound data chunk", FALSE);
  3089.         } elif (!strcmp(contents[which].name, "FADE"))
  3090.         {   chunkdesc("Fade away to silence", TRUE);
  3091.  
  3092.             if (!iff.raw)
  3093.             {   label("Fade start:");
  3094.                 uvalue = getulong(contents[which].DataPtr);
  3095.                 unumcat(uvalue, TRUE);
  3096.         }   }
  3097.         elif (!strcmp(contents[which].name, "SEQN"))
  3098.         {   chunkdesc("Multiple loop sequencing", TRUE);
  3099.  
  3100.         if (!iff.raw)
  3101.         {
  3102.             currentpos = 0;
  3103.             while (currentpos < contents[which].bytes)
  3104.             {   label("Loop start:");
  3105.                 uvalue = getulong(&(contents[which].DataPtr[currentpos]));
  3106.                 unumcat(uvalue, FALSE);
  3107.                 if (uvalue % 4)
  3108.                 {   strcat(tempstring1, "!");
  3109.                 }
  3110.                 addreactionnode(&List2, tempstring1);
  3111.                 currentpos += 4;
  3112.  
  3113.                 label("Loop end:");
  3114.                 uvalue = getulong(&(contents[which].DataPtr[currentpos]));
  3115.                 unumcat(uvalue, FALSE);
  3116.                 if (uvalue % 4)
  3117.                 {   strcat(tempstring1, "!");
  3118.                 }
  3119.                 addreactionnode(&List2, tempstring1);
  3120.                 currentpos += 4;
  3121.         }   }   }
  3122.         elif (!strcmp(contents[which].name, "CHAN"))
  3123.         {   chunkdesc("Specified channel, or combination of channels", TRUE);
  3124.  
  3125.             if (!iff.raw)
  3126.             {   label("Channel:");
  3127.                 svalue = getslong(contents[which].DataPtr);
  3128.                 if (svalue == 2)
  3129.                 {   strcat(tempstring1, "Left");
  3130.                 } elif (svalue == 4)
  3131.                 {   strcat(tempstring1, "Right");
  3132.                 } elif (svalue == 6)
  3133.                 {   strcat(tempstring1, "Stereo (both)");
  3134.                 } else strcat(tempstring1, "?");
  3135.                 addreactionnode(&List2, tempstring1);
  3136.         }   }
  3137.         elif (!strcmp(contents[which].name, "PAN "))
  3138.         {   chunkdesc("Stereo sound using a single array of data", TRUE);
  3139.  
  3140.             if (!iff.raw)
  3141.             {   label("Sound position:");
  3142.                 svalue = getslong(contents[which].DataPtr);
  3143.                 snumcat(svalue, FALSE);
  3144.                 strcat(tempstring1, "/65536 ");
  3145.                 if (svalue < 32768)
  3146.                 {    strcat(tempstring1, "(left)");
  3147.                 } elif (svalue > 32678)
  3148.                 {    strcat(tempstring1, "(right)");
  3149.                 } else
  3150.                 {    // assert(svalue == 32678);
  3151.                      strcat(tempstring1, "(centre)");
  3152.                 }
  3153.                 addreactionnode(&List2, tempstring1);
  3154.         }   }
  3155.         elif (!strcmp(contents[which].name, "VHDR"))
  3156.         {   chunkdesc("Playback parameters for the sampled waveforms", TRUE);
  3157.  
  3158.             if (!iff.raw)
  3159.             {   label("1-shot samples:");
  3160.                 uvalue = getulong(contents[which].DataPtr);
  3161.                 unumcat(uvalue, TRUE);
  3162.  
  3163.                 label("Repeat samples:");
  3164.                 uvalue = getulong(&(contents[which].DataPtr[4]));
  3165.                 unumcat(uvalue, TRUE);
  3166.  
  3167.                 label("Samples per cycle:");
  3168.                 uvalue = getulong(&(contents[which].DataPtr[8]));
  3169.                 unumcat(uvalue, TRUE);
  3170.  
  3171.                 label("Sampling rate:");
  3172.                 uvalue = getuword(&(contents[which].DataPtr[12]));
  3173.                 unumcat(uvalue, TRUE);
  3174.  
  3175.                 label("Octaves:");
  3176.                 snumcat((SLONG) contents[which].DataPtr[14], TRUE); // UBYTE
  3177.  
  3178.                 label("Compression:"); // UBYTE
  3179.                 interpret(48, (ULONG) contents[which].DataPtr[15]);
  3180.  
  3181.                 label("Volume:");
  3182.                 svalue = getslong(&(contents[which].DataPtr[16]));
  3183.                 svalue /= 1024; // LONG (Fixed)
  3184.                 snumcat(svalue, FALSE);
  3185.                 strcat(tempstring1, "/64");
  3186.                 addreactionnode(&List2, tempstring1);
  3187.     }   }   }
  3188.     elif (!strcmp(queryform, "ILBM") || !strcmp(queryform, "ABCM") || !strcmp(queryform, "ANIM"))
  3189.     {   if (!strcmp(contents[which].name, "CAMG"))
  3190.         {   chunkdesc("Amiga display mode of a picture", TRUE);
  3191.  
  3192.             if (!iff.raw)
  3193.             {   label("ModeID:");
  3194.                 strcat(tempstring1, "$");
  3195.                 hexalize(contents[which].DataPtr[0]);
  3196.                 hexalize(contents[which].DataPtr[1]);
  3197.                 hexalize(contents[which].DataPtr[2]);
  3198.                 hexalize(contents[which].DataPtr[3]);
  3199.                 addreactionnode(&List2, tempstring1);
  3200.         }   }
  3201.         elif (!strcmp(queryform, "ANIM") && !strcmp(contents[which].name, "ANHD"))
  3202.         {   chunkdesc("Animation header", TRUE);
  3203.  
  3204.         if (!iff.raw)
  3205.         {   label("Compression method:");
  3206.             if (contents[which].DataPtr[0] == 74) // not a typo
  3207.             {   strcat(tempstring1, "74 (Eric Graham)");
  3208.             } else
  3209.             {   interpret(49, (ULONG) contents[which].DataPtr[0]);
  3210.             }
  3211.  
  3212.             label("Mask:");
  3213.             strcat(tempstring1, "%");
  3214.             binarize(contents[which].DataPtr[1]);
  3215.             addreactionnode(&List2, tempstring1);
  3216.  
  3217.             label("Entire width:");
  3218.             uvalue = getuword(&contents[which].DataPtr[2]); // UWORD
  3219.             unumcat(uvalue, FALSE);
  3220.             strcat(tempstring1, " pixels");
  3221.             addreactionnode(&List2, tempstring1);
  3222.  
  3223.             label("Entire height:");
  3224.             uvalue = getuword(&contents[which].DataPtr[4]); // UWORD
  3225.             unumcat(uvalue, FALSE);
  3226.             strcat(tempstring1, " pixels");
  3227.             addreactionnode(&List2, tempstring1);
  3228.  
  3229.             label("Width:");
  3230.             svalue = getsword(&contents[which].DataPtr[6]); // WORD
  3231.             snumcat(svalue, FALSE);
  3232.             strcat(tempstring1, " pixels");
  3233.             addreactionnode(&List2, tempstring1);
  3234.  
  3235.             label("Height:");
  3236.             svalue = getsword(&contents[which].DataPtr[8]); // WORD
  3237.             snumcat(svalue, FALSE);
  3238.             strcat(tempstring1, " pixels");
  3239.             addreactionnode(&List2, tempstring1);
  3240.  
  3241.             label("Absolute time:");
  3242.             uvalue = getulong(&contents[which].DataPtr[10]); // ULONG
  3243.             unumcat(uvalue, FALSE);
  3244.             strcat(tempstring1, "/60 of a second");
  3245.             addreactionnode(&List2, tempstring1);
  3246.  
  3247.             label("Relative time:");
  3248.             uvalue = getulong(&contents[which].DataPtr[14]); // ULONG
  3249.             unumcat(uvalue, FALSE);
  3250.             strcat(tempstring1, "/60 of a second");
  3251.             addreactionnode(&List2, tempstring1);
  3252.  
  3253.             label("Interleave:");
  3254.             if (contents[which].DataPtr[18] == 0)
  3255.             {   strcat(tempstring1, "0 (2 frames back)");
  3256.             } else
  3257.             {   stcl_d(tempstring2, contents[which].DataPtr[18]);
  3258.                 strcat(tempstring1, tempstring2);
  3259.                 strcat(tempstring1, " frames back");
  3260.             }
  3261.             addreactionnode(&List2, tempstring1);
  3262.  
  3263.             // now a pad byte (19)
  3264.  
  3265.             label("Flags:");
  3266.             uvalue = getulong(&contents[which].DataPtr[20]); // ULONG
  3267.  
  3268.             label(" Data length:");
  3269.             if (uvalue & 1)
  3270.             {   strcat(tempstring1, "Long");
  3271.             } else
  3272.             {   strcat(tempstring1, "Short");
  3273.             }
  3274.             addreactionnode(&List2, tempstring1);
  3275.  
  3276.             label(" Set/XOR:");
  3277.             if (uvalue & 2)
  3278.             {   strcat(tempstring1, "Set");
  3279.             } else
  3280.             {   strcat(tempstring1, "XOR");
  3281.             }
  3282.             addreactionnode(&List2, tempstring1);
  3283.  
  3284.             label(" Info:");
  3285.             if (uvalue & 4)
  3286.             {   strcat(tempstring1, "One info list for all planes");
  3287.             } else
  3288.             {   strcat(tempstring1, "Separate info for each plane");
  3289.             }
  3290.             addreactionnode(&List2, tempstring1);
  3291.  
  3292.             label(" Run length encoded?");
  3293.             dobool((UBYTE) (uvalue & 8));
  3294.  
  3295.             label(" Encoding:");
  3296.             if (uvalue & 16)
  3297.             {   strcat(tempstring1, "Vertical");
  3298.             } else
  3299.             {   strcat(tempstring1, "Horizontal");
  3300.             }
  3301.             addreactionnode(&List2, tempstring1);
  3302.  
  3303.             label(" Info offsets:");
  3304.             if (uvalue & 32)
  3305.             {   strcat(tempstring1, "Short");
  3306.             } else
  3307.             {   strcat(tempstring1, "Long");
  3308.             }
  3309.             addreactionnode(&List2, tempstring1);
  3310.  
  3311.             // now 16 reserved bytes
  3312.         }   }
  3313.         elif (!strcmp(queryform, "ANIM") && !strcmp(contents[which].name, "DLTA"))
  3314.         {   chunkdesc("Delta compression data", FALSE);
  3315.         } elif (!strcmp(contents[which].name, "DPI "))
  3316.         {   chunkdesc("Dots per inch", TRUE);
  3317.  
  3318.             if (!iff.raw)
  3319.             {   label("Dots per inch:");
  3320.                 // There are 20 characters in the first column.
  3321.                 uvalue = getuword(contents[which].DataPtr);
  3322.                 unumcat(uvalue, FALSE);
  3323.                 strcat(tempstring1, "x");
  3324.                 uvalue = getuword(&(contents[which].DataPtr[2]));
  3325.                 unumcat(uvalue, TRUE);
  3326.         }   }
  3327.         elif (!strcmp(contents[which].name, "CMAP"))
  3328.         {   chunkdesc("Colour map data", FALSE);
  3329.         } elif (!strcmp(contents[which].name, "BODY"))
  3330.         {   chunkdesc("Image data chunk", FALSE);
  3331.         } elif (!strcmp(contents[which].name, "EPSF"))
  3332.         {   chunkdesc("Encapsulated PostScript representation of image", TRUE);
  3333.  
  3334.         if (!iff.raw)
  3335.         {
  3336.             label("Left X:");
  3337.             svalue = getsword(contents[which].DataPtr);
  3338.             snumcat(svalue, TRUE);
  3339.  
  3340.             label("Top Y:");
  3341.             svalue = getsword(&(contents[which].DataPtr[2]));
  3342.             snumcat(svalue, TRUE);
  3343.  
  3344.             label("Right X:");
  3345.             svalue = getsword(&(contents[which].DataPtr[4]));
  3346.             snumcat(svalue, TRUE);
  3347.  
  3348.             label("Bottom Y:");
  3349.             svalue = getsword(&(contents[which].DataPtr[6]));
  3350.             snumcat(svalue, TRUE);
  3351.         }   }
  3352.         elif (!strcmp(contents[which].name, "DEST"))
  3353.         {   chunkdesc("Scatter bitplanes into a deeper destination image", TRUE);
  3354.  
  3355.         if (!iff.raw)
  3356.         {
  3357.             label("Source bitplanes:");
  3358.             snumcat((SLONG) contents[which].DataPtr[0], TRUE);
  3359.  
  3360.             // next (1) is a pad byte.
  3361.  
  3362.             label("PlanePick:");
  3363.             strcat(tempstring1, "%"); // UWORD
  3364.             binarize(contents[which].DataPtr[2]);
  3365.             binarize(contents[which].DataPtr[3]);
  3366.             addreactionnode(&List2, tempstring1);
  3367.  
  3368.             label("PlaneOnOff:");
  3369.             strcat(tempstring1, "%"); // UWORD
  3370.             binarize(contents[which].DataPtr[4]);
  3371.             binarize(contents[which].DataPtr[5]);
  3372.             addreactionnode(&List2, tempstring1);
  3373.  
  3374.             label("PlaneMask:");
  3375.             strcat(tempstring1, "%"); // UWORD
  3376.             binarize(contents[which].DataPtr[6]);
  3377.             binarize(contents[which].DataPtr[7]);
  3378.             addreactionnode(&List2, tempstring1);
  3379.         }   }
  3380.         elif (!strcmp(contents[which].name, "GRAB"))
  3381.         {   chunkdesc("Locates a hotspot, when used as a pointer or brush", TRUE);
  3382.  
  3383.             if (!iff.raw)
  3384.             {   label("Hotspot:");
  3385.                 svalue = getsword(contents[which].DataPtr);
  3386.                 snumcat(svalue, FALSE);
  3387.                 strcat(tempstring1, ",");
  3388.                 svalue = getsword(&(contents[which].DataPtr[2]));
  3389.                 snumcat(svalue, TRUE);
  3390.         }   }
  3391.         elif (!strcmp(contents[which].name, "SPRT"))
  3392.         {   chunkdesc("This image is intended as a sprite", TRUE);
  3393.  
  3394.             if (!iff.raw)
  3395.             {   label("Precedence:");
  3396.                 uvalue = getuword(contents[which].DataPtr);
  3397.                 unumcat(uvalue, TRUE);
  3398.         }   }
  3399.         elif (!strcmp(contents[which].name, "BMHD"))
  3400.         {   /* UWORD w, h;               0-1, 2-3
  3401.             WORD  x, y;                  4-5, 6-7
  3402.             UBYTE nPlanes;               8
  3403.             UBYTE Masking;               9
  3404.             UBYTE Compression;           10
  3405.             UBYTE pad;                   11
  3406.             UWORD transparentColour;     12-13
  3407.             UBYTE xAspect, yAspect;      14, 15
  3408.             WORD  pageWidth, pageHeight; 16-17, 18-19 */
  3409.  
  3410.             chunkdesc("Data necessary to understand the BODY chunk", TRUE);
  3411.  
  3412.             if (!iff.raw)
  3413.             {
  3414.             label("Image size:");
  3415.             uvalue = getuword(contents[which].DataPtr); // UWORD
  3416.             unumcat(uvalue, FALSE);
  3417.             strcat(tempstring1, "x");
  3418.             uvalue = getuword(&(contents[which].DataPtr[2])); // UWORD
  3419.             unumcat(uvalue, TRUE);
  3420.  
  3421.             label("Position:");
  3422.             svalue = getsword(&(contents[which].DataPtr[4])); // WORD
  3423.             snumcat(svalue, FALSE);
  3424.             strcat(tempstring1, ",");
  3425.             svalue = getsword(&(contents[which].DataPtr[6])); // WORD
  3426.             snumcat(svalue, TRUE);
  3427.  
  3428.             label("Bitplanes:");
  3429.             snumcat((SLONG) contents[which].DataPtr[8], TRUE);
  3430.             // tell number of colours to user?
  3431.  
  3432.             label("Masking:");
  3433.             interpret(45, (ULONG) contents[which].DataPtr[9]);
  3434.  
  3435.             label("Compression:");
  3436.             interpret(46, (ULONG) contents[which].DataPtr[10]);
  3437.  
  3438.             // Next (11) is a pad byte.
  3439.  
  3440.             label("Transparent colour:");
  3441.             if (contents[which].DataPtr[9] != 2
  3442.              && contents[which].DataPtr[9] != 3)
  3443.             {   strcat(tempstring1, "n/a");
  3444.                 addreactionnode(&List2, tempstring1);
  3445.             } else
  3446.             {   uvalue = getuword(&(contents[which].DataPtr[12]));
  3447.                 unumcat(uvalue, TRUE);
  3448.             }
  3449.  
  3450.             label("Aspect ratio:");
  3451.             snumcat((SLONG) contents[which].DataPtr[14], FALSE);
  3452.             strcat(tempstring1, ":");
  3453.             snumcat((SLONG) contents[which].DataPtr[15], TRUE);
  3454.  
  3455.             label("Page size:");
  3456.             svalue = getsword(&(contents[which].DataPtr[16])); // WORD
  3457.             snumcat(svalue, FALSE);
  3458.             strcat(tempstring1, "x");
  3459.             svalue = getsword(&(contents[which].DataPtr[18])); // WORD
  3460.             snumcat(svalue, TRUE);
  3461.     }   }   }
  3462.     elif (!strcmp(queryform, "RSND"))
  3463.     {   if (!strcmp(contents[which].name, "RSHD"))
  3464.         {   chunkdesc("Sound header", TRUE);
  3465.  
  3466.             if (!iff.raw)
  3467.             {   label("Length:");
  3468.                 uvalue = getulong(contents[which].DataPtr); // ULONG
  3469.                 unumcat(uvalue, TRUE);
  3470.  
  3471.                 label("Frequency:");
  3472.                 uvalue = getulong(&contents[which].DataPtr[4]); // ULONG
  3473.                 unumcat(uvalue, TRUE);
  3474.  
  3475.                 label("Bits per sample:");
  3476.                 uvalue = getulong(&contents[which].DataPtr[8]); // ULONG
  3477.                 unumcat(uvalue, TRUE);
  3478.  
  3479.                 label("Number of channels:");
  3480.                 uvalue = getulong(&contents[which].DataPtr[12]); // ULONG
  3481.                 unumcat(uvalue, TRUE);
  3482.         }   }
  3483.         elif (!strcmp(contents[which].name, "RBOD"))
  3484.         {   chunkdesc("Sound body", FALSE);
  3485.     }   }
  3486.  
  3487.     if (!known || iff.raw)
  3488.     {   for (i = 0; i < contents[which].bytes; i += BYTESPERLINE)
  3489.         {   strcpy(tempstring1, "$");
  3490.  
  3491.             hexalize(i / 16777216); // do 1st byte
  3492.             j = i % 16777216;       // remove 1st byte
  3493.             hexalize(j / 65536);    // do 2nd byte
  3494.             j %= 65536;             // remove 2nd byte
  3495.             hexalize(j / 256);      // do 3rd byte
  3496.             hexalize(j % 256);      // do 4th byte
  3497.  
  3498.             strcat(tempstring1, ": ");
  3499.             for (j = 0; j < BYTESPERLINE; j++)
  3500.             {   if (contents[which].bytes > i + j)
  3501.                 {   hexalize(contents[which].DataPtr[i + j]);
  3502.                 } else
  3503.                 {   strcat(tempstring1, "##");
  3504.                 }
  3505.                 if (j % 2)
  3506.                 {   strcat(tempstring1, " ");
  3507.             }   }
  3508.             for (j = 0; j < BYTESPERLINE; j++)
  3509.             {   if (contents[which].bytes > i + j)
  3510.                 {   if (contents[which].DataPtr[i + j] < ' ') // if an unprintable character
  3511.                     {   strcat(tempstring1, ".");
  3512.                     } else
  3513.                     {   length = strlen(tempstring1);
  3514.                         tempstring1[length] = contents[which].DataPtr[i + j];
  3515.                         tempstring1[length + 1] = 0;
  3516.                 }   }
  3517.                 else
  3518.                 {   strcat(tempstring1, "#");
  3519.             }   }
  3520.             addreactionnode(&List2, tempstring1);
  3521.     }   }
  3522.     if (!known)
  3523.     {   chunkdesc("?", FALSE);
  3524.     }
  3525.  
  3526.     SetGadgetAttrs
  3527.     (   iff_gadgets[GID_6_LB2],
  3528.         MainWindowPtr, NULL,
  3529.         LISTBROWSER_Labels, &List2,
  3530.         TAG_END
  3531.     );
  3532. }
  3533.  
  3534. MODULE void chunkdesc(STRPTR desc, ABOOL isknown)
  3535. {   SetGadgetAttrs
  3536.     (   iff_gadgets[GID_6_ST4],
  3537.         MainWindowPtr, NULL,
  3538.         STRINGA_TextVal, desc,
  3539.         TAG_END
  3540.     );
  3541.     known = isknown;
  3542. }
  3543.  
  3544. MODULE void binarize(UBYTE data)
  3545. {   SLONG i; // must be signed
  3546.  
  3547.     for (i = 7; i >= 0; i--)
  3548.     {   if (data & (1 << i))
  3549.         {   strcat(tempstring1, "1");
  3550.         } else
  3551.         {   strcat(tempstring1, "0");
  3552. }   }   }
  3553.  
  3554. MODULE void hexalize(UBYTE data)
  3555. {   // Converts an unsigned byte into a hexadecimal string
  3556.  
  3557.     // do the high byte
  3558.     if (data / 16 >= 10)
  3559.     {   tempstring2[0] = (data / 16) - 10 + 'A'; // must be done in this order to prevent overflow during calculation of the value
  3560.     } else
  3561.     {   tempstring2[0] = (data / 16) + '0';
  3562.     }
  3563.  
  3564.     // now the low byte
  3565.     if (data % 16 >= 10)
  3566.     {   tempstring2[1] = (data % 16) - 10 + 'A';
  3567.     } else
  3568.     {   tempstring2[1] = (data % 16) + '0';
  3569.     }
  3570.     tempstring2[2] = 0;
  3571.     strcat(tempstring1, tempstring2);
  3572. }
  3573.  
  3574. MODULE ULONG getulong(UBYTE* start)
  3575. {   return (ULONG) ((16777216 * *(start    ))
  3576.                   + (   65536 * *(start + 1))
  3577.                   + (     256 * *(start + 2))
  3578.                   +             *(start + 3));
  3579. }
  3580. MODULE SLONG getslong(UBYTE* start)
  3581. {   return (SLONG) ((16777216 * *(start    ))
  3582.                   + (   65536 * *(start + 1))
  3583.                   + (     256 * *(start + 2))
  3584.                   +             *(start + 3));
  3585. }
  3586. MODULE ULONG getuword(UBYTE* start)
  3587. {   return (ULONG) ((     256 * *(start    ))
  3588.                   +             *(start + 1));
  3589. }
  3590. MODULE SLONG getsword(UBYTE* start)
  3591. {   return (SLONG) ((     256 * *(start    ))
  3592.                   +             *(start + 1));
  3593. }
  3594. MODULE SLONG getsbyte(UBYTE* start)
  3595. {   return (SBYTE) (*start);
  3596. }
  3597.  
  3598. MODULE void writeiffgadgets(void)
  3599. {   // update the gadgets according to variables
  3600.  
  3601.     SetGadgetAttrs
  3602.     (   iff_gadgets[GID_6_CB2], MainWindowPtr, NULL,
  3603.         GA_Selected, iff.obsolete,
  3604.     TAG_END);
  3605.     RefreshGadgets((struct Gadget *) iff_gadgets[GID_6_CB2], MainWindowPtr, NULL);
  3606.     SetGadgetAttrs
  3607.     (   iff_gadgets[GID_6_CB3], MainWindowPtr, NULL,
  3608.         GA_Selected, iff.private,
  3609.     TAG_END);
  3610.     RefreshGadgets((struct Gadget *) iff_gadgets[GID_6_CB3], MainWindowPtr, NULL);
  3611.     SetGadgetAttrs
  3612.     (   iff_gadgets[GID_6_CB4], MainWindowPtr, NULL,
  3613.         GA_Selected, iff.proposal,
  3614.     TAG_END);
  3615.     RefreshGadgets((struct Gadget *) iff_gadgets[GID_6_CB4], MainWindowPtr, NULL);
  3616.     SetGadgetAttrs
  3617.     (   iff_gadgets[GID_6_CB5], MainWindowPtr, NULL,
  3618.         GA_Selected, iff.reserved,
  3619.     TAG_END);
  3620.     RefreshGadgets((struct Gadget *) iff_gadgets[GID_6_CB5], MainWindowPtr, NULL);
  3621.     SetGadgetAttrs
  3622.     (   iff_gadgets[GID_6_CB6], MainWindowPtr, NULL,
  3623.         GA_Selected, iff.standard,
  3624.     TAG_END);
  3625.     RefreshGadgets((struct Gadget *) iff_gadgets[GID_6_CB6], MainWindowPtr, NULL);
  3626.     SetGadgetAttrs
  3627.     (   iff_gadgets[GID_6_CB7], MainWindowPtr, NULL,
  3628.         GA_Selected, iff.unregistered,
  3629.     TAG_END);
  3630.     RefreshGadgets((struct Gadget *) iff_gadgets[GID_6_CB7], MainWindowPtr, NULL);
  3631.     SetGadgetAttrs
  3632.     (   iff_gadgets[GID_6_CB8], MainWindowPtr, NULL,
  3633.         GA_Selected, iff.rkm,
  3634.     TAG_END);
  3635.     RefreshGadgets((struct Gadget *) iff_gadgets[GID_6_CB8], MainWindowPtr, NULL);
  3636.     SetGadgetAttrs
  3637.     (   iff_gadgets[GID_6_CB9], MainWindowPtr, NULL,
  3638.         GA_Selected, iff.cd,
  3639.     TAG_END);
  3640.     RefreshGadgets((struct Gadget *) iff_gadgets[GID_6_CB9], MainWindowPtr, NULL);
  3641.     SetGadgetAttrs
  3642.     (   iff_gadgets[GID_6_ST1],
  3643.         MainWindowPtr, NULL,
  3644.         STRINGA_TextVal, queryform,
  3645.         TAG_END
  3646.     );
  3647.     chunkdesc("-", FALSE);
  3648. }
  3649.  
  3650. MODULE void dotextattr(UBYTE* offset)
  3651. {   ULONG uvalue;
  3652.  
  3653.     // handles TextAttr structure (8 bytes)
  3654.     // name pointer is ignored
  3655.  
  3656.     label(" Height:");
  3657.     uvalue = getuword(offset + 4);
  3658.     unumcat(uvalue, TRUE);
  3659.  
  3660.     addreactionnode(&List2, " Style:");
  3661.  
  3662.     label("  Underlined?");
  3663.     dobool((*(offset + 6)) & 1); // FSF_UNDERLINED
  3664.  
  3665.     label("  Bold?");
  3666.     dobool((*(offset + 6)) & 2); // FSF_BOLD
  3667.  
  3668.     label("  Italic?");
  3669.     dobool((*(offset + 6)) & 4); // FSF_ITALIC
  3670.  
  3671.     label("  Extended?");
  3672.     dobool((*(offset + 6)) & 8); // FSF_EXTENDED
  3673.  
  3674.     label("  Colour font?");
  3675.     dobool((*(offset + 6)) & 64); // FSF_COLORFONT
  3676.  
  3677.     label("  Tagged?");
  3678.     dobool((*(offset + 6)) & 128); // FSF_TAGGED
  3679.  
  3680.     addreactionnode(&List2, " Flags:");
  3681.  
  3682.     label("  ROM font?");
  3683.     dobool((*(offset + 7)) & 1); // FPF_ROMFONT
  3684.  
  3685.     label("  Disk font?");
  3686.     dobool((*(offset + 7)) & 2); // FPF_DISKFONT
  3687.  
  3688.     label("  Reversed?");
  3689.     dobool((*(offset + 7)) & 4); // FPF_REVPATH
  3690.  
  3691.     label("  HiRes non-interlaced?");
  3692.     dobool((*(offset + 7)) & 8); // FPF_TALLDOT
  3693.  
  3694.     label("  LoRes interlaced?");
  3695.     dobool((*(offset + 7)) & 16); // FPF_WIDEDOT
  3696.  
  3697.     label("  Proportional?");
  3698.     dobool((*(offset + 7)) & 32); // FPF_PROPORTIONAL
  3699.  
  3700.     label("  Designed?");
  3701.     dobool((*(offset + 7)) & 64); // FPF_DESIGNED
  3702.  
  3703.     label("  Removed?");
  3704.     // this one has a ! after its `Yes', since it should never be TRUE.
  3705.     if (*(offset + 7) & 128) // FPF_REMOVED
  3706.     {   strcat(tempstring1, "Yes!");
  3707.     } else
  3708.     {   strcat(tempstring1, "No");
  3709.     }
  3710.     addreactionnode(&List2, tempstring1);
  3711. }
  3712.  
  3713. MODULE void docountry(UBYTE* offset)
  3714. {   ULONG uvalue;
  3715.  
  3716.     // handles CountryPrefs structure (8 bytes)
  3717.  
  3718.     // 16 reserved bytes at start
  3719.  
  3720.     label("Country code:");
  3721.     uvalue = getulong(offset + 16); // ULONG
  3722.     unumcat(uvalue, TRUE);
  3723.  
  3724.     label("Telephone code:");
  3725.     uvalue = getulong(offset + 20); // ULONG
  3726.     unumcat(uvalue, TRUE);
  3727.  
  3728.     label("Measuring system:");
  3729.     interpret(50, (ULONG) *(offset + 24));
  3730.  
  3731.     label("Long date/time format:");
  3732.     strcat(tempstring1, offset + 25); // 80 chars
  3733.     addreactionnode(&List2, tempstring1);
  3734.  
  3735.     label("Long date format:");
  3736.     strcat(tempstring1, offset + 105); // 40 chars
  3737.     addreactionnode(&List2, tempstring1);
  3738.  
  3739.     label("Long time format:");
  3740.     strcat(tempstring1, offset + 145); // 40 chars
  3741.     addreactionnode(&List2, tempstring1);
  3742.  
  3743.     label("Short date/time format:");
  3744.     strcat(tempstring1, offset + 185); // 80 chars
  3745.     addreactionnode(&List2, tempstring1);
  3746.  
  3747.     label("Short date format:");
  3748.     strcat(tempstring1, offset + 265); // 40 chars
  3749.     addreactionnode(&List2, tempstring1);
  3750.  
  3751.     label("Short time format:");
  3752.     strcat(tempstring1, offset + 305); // 40 chars
  3753.     addreactionnode(&List2, tempstring1);
  3754.  
  3755.     addreactionnode(&List2, "Numeric values:");
  3756.  
  3757.     label(" Decimal point:");
  3758.     strcat(tempstring1, offset + 345); // 10 chars
  3759.     addreactionnode(&List2, tempstring1);
  3760.  
  3761.     label(" Intgr group separator:");
  3762.     strcat(tempstring1, offset + 355); // 10 chars
  3763.     addreactionnode(&List2, tempstring1);
  3764.  
  3765.     label(" Frac. group separator:");
  3766.     strcat(tempstring1, offset + 365); // 10 chars
  3767.     addreactionnode(&List2, tempstring1);
  3768.  
  3769.     /* Integer group size (10 chars) and
  3770.        Fractional group size (10 chars): not strings (currently skipped */
  3771.  
  3772.     addreactionnode(&List2, "General monetary values:");
  3773.  
  3774.     label(" Decimal point:");
  3775.     strcat(tempstring1, offset + 395); // 10 chars
  3776.     addreactionnode(&List2, tempstring1);
  3777.  
  3778.     label(" Intgr group separator:");
  3779.     strcat(tempstring1, offset + 405); // 10 chars
  3780.     addreactionnode(&List2, tempstring1);
  3781.  
  3782.     label(" Frac. group separator:");
  3783.     strcat(tempstring1, offset + 415); // 10 chars
  3784.     addreactionnode(&List2, tempstring1);
  3785.  
  3786.     /* Integer group size (10 chars) and
  3787.        Fractional group size (10 chars): not strings (currently skipped) */
  3788.  
  3789.     addreactionnode(&List2, " Digits after decimal point:");
  3790.  
  3791.     label("  Intranational:");
  3792.     snumcat((SLONG) ((UBYTE) *(offset + 445)), TRUE);
  3793.  
  3794.     label("  International:");
  3795.     snumcat((SLONG) ((UBYTE) *(offset + 446)), TRUE);
  3796.  
  3797.     addreactionnode(&List2, "Currency symbols:");
  3798.  
  3799.     label(" Large amounts symbol:");
  3800.     strcat(tempstring1, offset + 447); // 10 chars
  3801.     addreactionnode(&List2, tempstring1);
  3802.  
  3803.     label(" Small amounts symbol:");
  3804.     strcat(tempstring1, offset + 457); // 10 chars
  3805.     addreactionnode(&List2, tempstring1);
  3806.  
  3807.     label(" ISO 4217 code:");
  3808.     strcat(tempstring1, offset + 467); // 10 chars
  3809.     addreactionnode(&List2, tempstring1);
  3810.  
  3811.     addreactionnode(&List2, "Positive monetary values:");
  3812.  
  3813.     label(" Positive sign:");
  3814.     strcat(tempstring1, offset + 477); // 10 chars
  3815.     addreactionnode(&List2, tempstring1);
  3816.  
  3817.     label(" Space next to sign?");
  3818.     interpret(51, (ULONG) *(offset + 487));
  3819.  
  3820.     label(" Positive sign pos.:");
  3821.     interpret(52, (ULONG) *(offset + 488));
  3822.  
  3823.     label(" Currency symbol pos.:");
  3824.     interpret(53, (ULONG) *(offset + 489));
  3825.  
  3826.     addreactionnode(&List2, "Negative monetary values:");
  3827.  
  3828.     label(" Negative sign:");
  3829.     strcat(tempstring1, offset + 500); // 10 chars
  3830.     addreactionnode(&List2, tempstring1);
  3831.  
  3832.     label(" Space next to sign?");
  3833.     interpret(51, (ULONG) *(offset + 500));
  3834.  
  3835.     label(" Negative sign pos.:");
  3836.     interpret(52, (ULONG) *(offset + 501));
  3837.  
  3838.     label(" Currency symbol pos.:");
  3839.     interpret(53, (ULONG) *(offset + 502));
  3840.  
  3841.     label("First day of the week:");
  3842.     interpret(54, (ULONG) *(offset + 503));
  3843. }
  3844.  
  3845. AGLOBAL void iff_init(void)
  3846. {   iff.raw = FALSE;
  3847.  
  3848.     NewList(&List1);
  3849.     NewList(&List2);
  3850. }
  3851.  
  3852. AGLOBAL void iff_die(void)
  3853. {   IOBuffer[19] = (UBYTE) iff.raw;
  3854. }
  3855.  
  3856. AGLOBAL void iff_config(void)
  3857. {   iff.raw = (ULONG) IOBuffer[19];
  3858. }
  3859.  
  3860. AGLOBAL ULONG Hook6Func(struct Hook *h, VOID *o, VOID *msg)
  3861. {   /* "When the hook is called, the data argument points to the 
  3862.     window object and message argument to the IntuiMessage." */
  3863.  
  3864.     UWORD code, qual;
  3865.     ULONG scroll = 0;
  3866.  
  3867.     geta4(); // wait till here before doing anything
  3868.  
  3869.     code = ((struct IntuiMessage *) msg)->Code;
  3870.     qual = ((struct IntuiMessage *) msg)->Qualifier;
  3871.  
  3872.     switch(code)
  3873.     {
  3874.     case SCAN_HELP:
  3875.         helpabout();
  3876.     break;
  3877.     case SCAN_ESCAPE:
  3878.         if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  3879.         {   cleanexit(EXIT_SUCCESS);
  3880.         } else page = 0;
  3881.     break;
  3882.     case SCAN_UP:
  3883.         if (qual & IEQUALIFIER_CONTROL)
  3884.         {   scroll = LBP_TOP;
  3885.         } elif (qual & IEQUALIFIER_LSHIFT || qual & IEQUALIFIER_RSHIFT)
  3886.         {   scroll = LBP_PAGEUP;
  3887.         } else scroll = LBP_LINEUP;
  3888.     break;
  3889.     case SCAN_DOWN:
  3890.         if (qual & IEQUALIFIER_CONTROL)
  3891.         {   scroll = LBP_BOTTOM;
  3892.         } elif (qual & IEQUALIFIER_LSHIFT || qual & IEQUALIFIER_RSHIFT)
  3893.         {   scroll = LBP_PAGEDOWN;
  3894.         } else scroll = LBP_LINEDOWN;
  3895.     break;
  3896.     case SCAN_PERIOD:
  3897.         if (asl("~(#?.info)"))
  3898.         {   strcpy(iff.pathname, aslresult);
  3899.  
  3900.             SetGadgetAttrs
  3901.             (   iff_gadgets[GID_6_ST6], MainWindowPtr, NULL,
  3902.                 STRINGA_TextVal, iff.pathname,
  3903.                 TAG_END
  3904.             ); // we don't know how many files in advance...
  3905.  
  3906.             readiff();
  3907.         }
  3908.     break;
  3909.     case SCAN_F:
  3910.         ActivateLayoutGadget(iff_gadgets[GID_6_LY1], MainWindowPtr, NULL, (Object) iff_gadgets[GID_6_ST1]);
  3911.     break;
  3912.     case SCAN_P:
  3913.         ActivateLayoutGadget(iff_gadgets[GID_6_LY1], MainWindowPtr, NULL, (Object) iff_gadgets[GID_6_ST6]);
  3914.     break;
  3915.     case SCAN_R:
  3916.         // the gadget is handled automatically by the system, all we need
  3917.         // to do is update our internal record of the state of the gadget
  3918.         if (!(GetAttr
  3919.         (   GA_Selected, iff_gadgets[GID_6_CB1], (ULONG *) &iff.raw
  3920.         )))
  3921.         {   rq("Unsupported inquiry!"); // should never happen
  3922.         }
  3923.         if (selectedchunk && known)
  3924.         {   tellchunk(selectedchunk);
  3925.         }
  3926.     break;
  3927.     default:
  3928.     break;
  3929.     }
  3930.  
  3931.     if (code == SCAN_UP || code == SCAN_DOWN)
  3932.     {   SetGadgetAttrs
  3933.         (   iff_gadgets[GID_6_LB2],       // pointer to gadget
  3934.             MainWindowPtr,                // pointer to window (not window object!)
  3935.             NULL,                         // pointer to requester
  3936.             LISTBROWSER_Position, scroll, // tags
  3937.             TAG_DONE                      // done
  3938.         );
  3939.     }
  3940.  
  3941.     return(1);
  3942. }
  3943.  
  3944. MODULE void label(STRPTR text)
  3945. {   ULONG i, length;
  3946.  
  3947.     length = strlen(text);
  3948.  
  3949.     strcpy(tempstring1, text);
  3950.     if (length < LABELLENGTH)
  3951.     {   for (i = length; i <= LABELLENGTH; i++)
  3952.         {   strcat(tempstring1, " ");
  3953. }   }   }
  3954.  
  3955. MODULE void dobool(UBYTE thebool)
  3956. {   if (thebool)
  3957.     {   strcat(tempstring1, "Yes");
  3958.     } else strcat(tempstring1, "No");
  3959.     addreactionnode(&List2, tempstring1);
  3960. }
  3961.  
  3962. MODULE void snumcat(SLONG thenumber, ABOOL finished)
  3963. {   stcl_d(tempstring2, thenumber);
  3964.     strcat(tempstring1, tempstring2);
  3965.  
  3966.     if (finished)
  3967.     {   addreactionnode(&List2, tempstring1);
  3968. }   }
  3969.  
  3970. MODULE void unumcat(ULONG thenumber, ABOOL finished)
  3971. {   stcul_d(tempstring2, thenumber);
  3972.     strcat(tempstring1, tempstring2);
  3973.  
  3974.     if (finished)
  3975.     {   addreactionnode(&List2, tempstring1);
  3976. }   }
  3977.  
  3978. MODULE void interpret(ULONG tablenum, ULONG value)
  3979. {   snumcat((SLONG) value, FALSE);
  3980.     strcat(tempstring1, " (");
  3981.  
  3982.     if (value > table[tablenum].entries)
  3983.     {   strcat(tempstring1, "?");
  3984.     } else
  3985.     {   strcat(tempstring1, table[tablenum].tablestring[value]);
  3986.     }
  3987.  
  3988.     strcat(tempstring1, ")");
  3989.     addreactionnode(&List2, tempstring1);
  3990. }
  3991.